根据条件用不同的替换dict替换pandas数据帧列中的值



我有一个数据帧,我想在其中替换列中的值,但描述替换的dict基于另一列中的数值。示例数据帧如下所示:

Map me strings        date
0       1   test1  2020-01-01
1       2   test2  2020-02-10
2       3   test3  2020-01-01
3       4   test2  2020-03-15

我有一本字典,看起来像这样:

map_dict = {'2020-01-01': {1: 4, 2: 3, 3: 1, 4: 2},
'2020-02-10': {1: 3, 2: 4, 3: 1, 4: 2},
'2020-03-15': {1: 3, 2: 2, 3: 1, 4: 4}}

我希望映射逻辑根据日期而有所不同。

在本例中,预期输出为:

Map me strings        date
0       4   test1  2020-01-01
1       4   test2  2020-02-10
2       1   test3  2020-01-01
3       4   test2  2020-03-15

我有一个巨大的数据帧(100M+行(,所以如果可能的话,我真的想避免任何循环解决方案。

我试着想办法使用地图或替换,但没有成功

DataFrame.joinDataFrame共导入器和DataFrame.stack:创建的MultiIndex Series一起使用

df = df.join(pd.DataFrame(map_dict).stack().rename('new'), on=['Map me','date'])
print (df)
Map me strings        date  new
0       1   test1  2020-01-01    4
1       2   test2  2020-02-10    4
2       3   test3  2020-01-01    1
3       4   test2  2020-03-15    4

也许试试这样的东西?

df['mapped'] = df.apply(lambda x: map_dict[x['date']][x['Map me']], axis=1)

尝试np.其中,它通常比pandas:性能更好

df["Mapped"] = ""
for key in map_dict.keys():
df["Mapped"] = np.where((df["date"] == key)&(df["Mapped"] == ""), df["Map me"].apply(lambda x: map_dict[key][x]), df["Mapped"])

结果:

Map me  strings date    Mapped
0   1   test1   2020-01-01  4
1   2   test2   2020-02-10  4
2   3   test3   2020-01-01  1
3   4   test2   2020-03-15  4

一种更像熊猫的方法是将map_dict转换为DataFrame,并将其连接到示例帧中。例如:

# Create the original dataframe
>>> df = pd.DataFrame([(1, 'test1', '2020-01-01'), (2, 'test2', '2020-02-10'), (3, 'test3', '2020-01-01'), (4, 'test2', '2020-03-15')], columns=['Map me', 'strings', 'date'])
>>> df
Map me strings        date
0       1   test1  2020-01-01
1       2   test2  2020-02-10
2       3   test3  2020-01-01
3       4   test2  2020-03-15
# Convert the map dict to a dataframe
>>> map_df = pd.DataFrame([(k, j, l) for k, v in map_dict.items() for j,l in v.items()], columns=['date', 'Map me', 'Map to'])
>>> map_df
date  Map me  Map to
0   2020-01-01       1       4
1   2020-01-01       2       3
2   2020-01-01       3       1
3   2020-01-01       4       2
4   2020-02-10       1       3
5   2020-02-10       2       4
6   2020-02-10       3       1
7   2020-02-10       4       2
8   2020-03-15       1       3
9   2020-03-15       2       2
10  2020-03-15       3       1
11  2020-03-15       4       4
# Perform the join
>>> mapped_df = pd.merge(df, map_df, left_on=['date', 'Map me'], right_on=['date', 'Map me'])
>>> mapped_df
Map me strings        date  Map to
0       1   test1  2020-01-01       4
1       2   test2  2020-02-10       4
2       3   test3  2020-01-01       1
3       4   test2  2020-03-15       4
>>>