我偶然发现了熊猫中的一个小问题。我有两个数据框。第一个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
相应的字段值。
以上所述,我有三个问题:
df_1.replace
方法替换各个字段? df_1
中正确的日期替换df_2
中的日期部分的正确方法是什么? 答案 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>。
答案 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)
结果: