我有一个数据帧,它有两列level1和level2。级别1中的每个帐号都链接到列级别2中的ParentID。
df = pd.DataFrame([[7854568400,489],
[9632588400,126],
[3699633691,189],
[9876543697,987],
[7854568409,396],
[7854567893,897],
[9632588409,147]],
columns = ['level1','level2'])
df
输出:
level1 level2
0 7854568400 489
1 9632588400 126
2 3699633691 189
3 9876543697 987
4 7854568409 396
5 7854567893 897
6 9632588409 147
对于以";8409";在列";级别1";它们被映射到级别2中错误的ParentID。为了找到正确的ParentID,你需要在级别1中搜索,在那里你替换所有以"结尾的帐户;8409";用";8400";。然后,它将在同一列中找到其等效帐户。在找到匹配的地方,复制列"中的内容;级别2";并将其替换为以";8409";。
在下面的期望输出中7854568409";其级别2从396变为489(取自第0行(9632588409";其级别2从147变为126(取自第1行(。请注意,在列"中没有任何内容被编辑;级别1";仅在";级别2";。
期望输出:
level1 level2
0 7854568400 489
1 9632588400 126
2 3699633691 189
3 9876543697 987
4 7854568409 489
5 7854567893 897
6 9632588409 126
任何关于如何实现这一目标的想法都将是伟大的。
您可能想从确定哪些level1值以8409结尾开始。您可以使用pd.Series.str((命令来完成此操作。
ends_with_8409 = df["level1"].astype( str ).str[-4:] == "8409"
这将创建一个长度与df["level1"]
相同的布尔序列,现在您知道了在level2中哪些行需要替换。
现在,为了获得这些行的适当level2值,您可能需要进行合并(尤其是如果数据集很大,这将比映射或应用备选方案快得多(。
df["temp_level1"] = df["level1"].where( ~ends_with_8409, df["level1"].astype( str ).str[0:-4] + "8400" ).astype( int )
final_df = df[ ["temp_level1"] ].merge( df[ ["level1","level2"] ], left_on = "temp_level1", right_on = "level1", how="left" ).drop( columns="temp_level1" )
在这里,我们创建一个列,该列替换以"0"结尾的每个level1值;8409";具有相同的值但以"0"结尾;8400";。然后,将其合并到原始数据帧上,以获得适当的级别2匹配。
final_df[ "level1" ] = final_df[ "level1" ].where( ~ends_with_8409, final_df.astype( str ).str[0:-4] + "8409" ).astype( int )
最后,再次使用ends_with_8409
布尔掩码,替换相关的level1值,使得它们以"0"结尾;8409";再一次
>>> final_df
level1 level2
0 7854568400 489
1 9632588400 126
2 3699633691 189
3 9876543697 987
4 7854568409 489
5 7854567893 897
6 9632588409 126
不幸的是,我认为你不能多次使用astype。pd.Series.str((仅在该系列为字符串类型时有效,而合并仅在合并的列为相同类型时有效。这是关于pd.DataFrame.where((.的文档
您可以从df
与df
的自合并中更新level2
列,在后者(合并右侧(中,level1
列更新为正确的帐号:
import pandas as pd
df = pd.DataFrame([[7854568400,489],
[9632588400,126],
[3699633691,189],
[9876543697,987],
[7854568409,396],
[7854567893,897],
[9632588409,147]],
columns = ['level1','level2'])
df.level2 = df.merge(df.assign(level1 = df.level1.astype(str).str.replace('8409$', '8400', regex=True).astype('int64')), on='level1', how='right')['level2_x']
结果:
level1 level2
0 7854568400 489
1 9632588400 126
2 3699633691 189
3 9876543697 987
4 7854568409 489
5 7854567893 897
6 9632588409 126