将 DataFrame 列的值更改为第二列的值,条件是 pandas 中第三列的值

Change the value of a dataframe column to the value of a second column conditional on the value of a third column in pandas

提问人:hallque 提问时间:3/6/2022 最后编辑:hallque 更新时间:3/6/2022 访问量:100

问:

我有包含公司当前名称、旧名称和名称更改日期的数据。它看起来像这样:

名字 former_name1 name_change_date1
ACMAT公司 鱼肚
ACME电气公司 鱼肚
ACME联合公司 鱼肚
哥伦比亚橡果信托 自由橡果信托 2003-10-20
多图形公司 AM国际公司 1997-03-17
米勒·劳埃德一世三世 鱼肚
附属计算机服务公司 鱼肚
亚当斯资源与能源公司 亚当斯资源与能源公司 2005-04-01
BK 技术公司 BK Technologies, Inc.(BK技术公司) 2019-03-28

我想弄清楚每家公司在特定日期的名称是什么。假设我想弄清楚一家公司截至 2002 年 1 月 1 日的名称。然后,我可以创建一个名为 say, 的新列,该列将包含公司的当前名称,除非该公司自 2002 年 1 月 1 日以来更改了名称,在这种情况下,它将包含公司的历史名称(即 )。因此,输出应如下所示:edited_nameformer_name1

名字 former_name1 name_change_date1 edited_name
ACMAT公司 鱼肚 ACMAT公司
ACME电气公司 鱼肚 ACME电气公司
ACME联合公司 鱼肚 ACME联合公司
哥伦比亚橡果信托 自由橡果信托 2003-10-20 自由橡果信托
多图形公司 AM国际公司 1997-03-17 多图形公司
米勒·劳埃德一世三世 鱼肚 米勒·劳埃德一世三世
附属计算机服务公司 鱼肚 附属计算机服务公司
亚当斯资源与能源公司 亚当斯资源与能源公司 2005-04-01 亚当斯资源与能源公司
BK 技术公司 BK Technologies, Inc.(BK技术公司) 2019-03-28 BK Technologies, Inc.(BK技术公司)

在 Stata(我更熟悉)中,这可以通过以下方式轻松实现:

gen edited_name = name
replace edited_name = former_name1 if name_change_date_1 > date("2002-01-01", "YMD") & name_change_date_1 != .

不幸的是,我不知道如何在 Python/Pandas 中完成此操作。

数据:

{'name': ['ACMAT CORP', 'ACME ELECTRIC CORP', 'ACME UNITED CORP', 'COLUMBIA ACORN TRUST',
          'MULTIGRAPHICS INC', 'MILLER LLOYD I III', 'AFFILIATED COMPUTER SERVICES INC',
          'ADAMS RESOURCES & ENERGY, INC.', 'BK Technologies Corp'],
 'former_name1': [nan, nan, nan, 'LIBERTY ACORN TRUST', 'AM INTERNATIONAL INC', nan, nan,
                  'ADAMS RESOURCES & ENERGY INC', 'BK Technologies, Inc.'],
 'name_change_date1': [NaT, NaT, NaT, '2003-10-20', '1997-03-17', NaT, NaT,
                       '2005-04-01', '2019-03-28']}
Python Pandas 数据帧 布尔逻辑

评论

1赞 keramat 3/6/2022
您能以我们可以复制的格式提供数据吗?
0赞 mozway 3/6/2022
另外,您认为公司一直存在吗?如果您在日期“1800-01-01”请求名称,会发生什么?

答:

2赞 user7864386 3/6/2022 #1

您可以使用 numpy.where 根据是否发生名称更改来选择值:

import numpy as np
df['edited_name'] = np.where(df['name_change_date1'].notna() & 
                             df['name_change_date1'].gt(pd.to_datetime('1/1/2002')), 
                             df['former_name1'], df['name'])

或带口罩

df['edited_name'] = df['name'].mask(df['name_change_date1'].notna() & 
                                    df['name_change_date1'].gt(pd.to_datetime('1/1/2002')), 
                                    df['former_name1'])

输出:

                               name                  former_name1  \
0                        ACMAT CORP                           NaN   
1                ACME ELECTRIC CORP                           NaN   
2                  ACME UNITED CORP                           NaN   
3              COLUMBIA ACORN TRUST           LIBERTY ACORN TRUST   
4                 MULTIGRAPHICS INC          AM INTERNATIONAL INC   
5                MILLER LLOYD I III                           NaN   
6  AFFILIATED COMPUTER SERVICES INC                           NaN   
7    ADAMS RESOURCES & ENERGY, INC.  ADAMS RESOURCES & ENERGY INC   
8              BK Technologies Corp         BK Technologies, Inc.   

  name_change_date1                       edited_name  
0               NaT                        ACMAT CORP  
1               NaT                ACME ELECTRIC CORP  
2               NaT                  ACME UNITED CORP  
3        2003-10-20               LIBERTY ACORN TRUST  
4        1997-03-17                 MULTIGRAPHICS INC  
5               NaT                MILLER LLOYD I III  
6               NaT  AFFILIATED COMPUTER SERVICES INC  
7        2005-04-01      ADAMS RESOURCES & ENERGY INC  
8        2019-03-28             BK Technologies, Inc.  
0赞 keramat 3/6/2022 #2

用:

import numpy as np
df = pd.DataFrame({'name':['a', 'b', 'c', 'd'], 'fname':[np.nan, 'h', 's', np.nan], 'dc':[np.nan, '2003-10-20', '1997-03-17', np.nan]})
df['dc'] = pd.to_datetime(df['dc'])
df['nname'] = df['fname'][df['dc']>'1/1/2002']
res = df['name'][df['nname'].isna()]
temp = df['fname'][df['nname'].notna()]
res = res.append(temp)
df['res']=res

输出:

enter image description here