熊猫:将列值替换为从其他数据框中获取的值

时间:2019-08-25 19:06:09

标签: python pandas

我偶然发现了熊猫中的一个小问题。我有两个数据框。第一个df_1如下

vendor_name     date            company_name     state
PERTH          is june 2019     Abc enterprise   Kentucky
Megan Ent      25-april-2019    Xyz Fincorp      Texas

第二个df_2包含df_1中每一列的正确值。

df_2
Field          wrong value     correct value
vendor_name    PERTH           Perth Enterprise
date           is              15   ## this means that is should be read as 15
company_name   Abc enterprise  ABC International Enterprise Inc.

为了用df_1中的值(date字段除外)替换正确的值,我正在使用pandas.loc方法。下面是代码片段

vend = df_1['vendor_Name'].tolist()
comp = df_1['company_name'].tolist()
state = df_1['state'].tolist()

for i in vend:
   if df_2['wrong value'].str.contains(i):
      crct = df_2.loc[df_2['wrong value'] == i,'correct value'].tolist()

类似地,对于公司和州,我遵循上述方式。 但是,crct返回一个空白序列。理想情况下,它应该返回

['Perth Enterprise','Abc International Enterprise Inc']

下一步将是通过上面的列表replace相应的字段值。

以上所述,我有三个问题:

  1. 为什么上面的代码生成空白列表?我在这里想念什么?
  2. 如何使用df_1.replace方法替换各个字段?
  3. df_1中正确的日期替换df_2中的日期部分的正确方法是什么?

3 个答案:

答案 0 :(得分:1)

编辑:当数据具有循环替换(即键和值重叠)时,整个数据帧的替换将失败。在这种情况下,请逐列进行,然后concat一起进行。最后,使用join添加df1中所有缺少的列:

df_replace = pd.concat([df1[k].replace(val, regex=True) for k, val in d.items()], axis=1).join(df1.state)

原始: 我在交互式环境中尝试了您的代码,但在ValueError: The truth value of a Series is ambiguous上给出了错误df_2['wrong value'].str.contains(i)

假设您有多个供应商名称,所以简单的方法是根据df2的groupby构造一个字典,并将其与df.replace上的df1一起使用。

d = {k: gp.set_index('wrong value')['correct value'].to_dict() 
               for k, gp in df2.groupby('Field')}

Out[64]:
{'company_name': {'Abc enterprise': 'ABC International Enterprise Inc. '},
 'date': {'is': '15'},
 'vendor_name': {'PERTH': 'Perth Enterprise'}}

df_replace = df1.replace(d, regex=True)    
print(df_replace)

In [68]:
        vendor_name           date                        company_name  \
0  Perth Enterprise   15 june 2019  ABC International Enterprise Inc.
1         Megan Ent  25-april-2019                         Xyz Fincorp

      state
0  Kentucky
1     Texas 

注意:您的示例df2仅对供应商PERTH具有价值,因此仅替换第一行。当您在vendor_names中拥有所有df2时,它将替换在df1中的所有{

答案 1 :(得分:0)

定义以下 replace 函数:

def repl(row):
    fld = row.Field
    v1 = row['wrong value']
    v2 = row['correct value']
    updInd = df_1[df_1[fld].str.contains(v1)].index
    df_1.loc[updInd, fld] = df_1.loc[updInd, fld]\
        .str.replace(re.escape(v1), v2)

然后为 df_2 中的每一行调用它:

for _, row in df_2.iterrows():
    repl(row)

请注意,单独的 str.replace 不需要 import re Pandas 将其导入引擎盖下)。 但是在上面的函数中, re.escape 从我们的代码中被显式调用, 因此,重新导入是必需的。

答案 2 :(得分:0)

一种简单的方法是遍历第一个数据帧,然后替换错误的值:

Result = pd.DataFrame()
for i in range(len(df1)):
    vendor_name = df1.iloc[i]['vendor_name']
    date = df1.iloc[i]['date']
    company_name = df1.iloc[i]['company_name']

    if vendor_name in df2['wrong value'].values:
        vendor_name = df2.loc[df2['wrong value'] == vendor_name]['correct value'].values[0]
    if company_name in df2['wrong value'].values:
        company_name = df2.loc[df2['wrong value'] == company_name]['correct value'].values[0]

    new_row = {'vendor_name':[vendor_name],'date':[date],'company_name':[company_name]}    
    new_row = pd.DataFrame(new_row,columns=['vendor_name','date','company_name'])
    Result = Result.append(new_row,ignore_index=True)

结果:

enter image description here