我有一个df
:
ColA ColB
1 1
2 3
2 2
1 2
1 3
2 1
我想使用两个不同的字典来更改ColB中的值。如果ColA中的值为1,我想使用d1
,如果ColB中的值为2,我想使用d2
。
d1 = {1:'a',2:'b',3:'c'}
d2 = {1:'d',2:'e',3:'f'}
结果:
ColA ColB
1 a
2 f
2 e
1 b
1 c
2 d
实现这一目标的最佳方法是什么?
答案 0 :(得分:11)
一种方法是根据一个map
的值使用np.where
来ColB
ColA
中的值,而使用一个字典或另一个字典:
import numpy as np
df['ColB'] = np.where(df.ColA.eq(1), df.ColB.map(d1), df.ColB.map(d2))
哪个给:
ColA ColB
0 1 a
1 2 f
2 2 e
3 1 b
4 1 c
5 2 d
对于更通用的解决方案,您可以使用np.select
,它适用于多种条件。让我们在ColA
和字典中添加另一个值,以了解如何使用三种不同的映射来完成此操作:
print(df)
ColA ColB
0 1 1
1 2 3
2 2 2
3 1 2
4 3 3
5 3 1
values_to_map = [1,2,3]
d1 = {1:'a',2:'b',3:'c'}
d2 = {1:'d',2:'e',3:'f'}
d3 = {1:'g',2:'h',3:'i'}
#create a list of boolean Series as conditions
conds = [df.ColA.eq(i) for i in values_to_map]
# List of Series to choose from depending on conds
choices = [df.ColB.map(d) for d in [d1,d2,d3]]
# use np.select to select form the choice list based on conds
df['ColB'] = np.select(conds, choices)
结果:
ColA ColB
0 1 a
1 2 f
2 2 e
3 1 b
4 3 i
5 3 g
答案 1 :(得分:7)
您可以使用新的字典,其中的键是tuple
,并将其映射到压缩的列。
d = {**{(1, k): v for k, v in d1.items()}, **{(2, k): v for k, v in d2.items()}}
df.assign(ColB=[*map(d.get, zip(df.ColA, df.ColB))])
ColA ColB
0 1 a
1 2 f
2 2 e
3 1 b
4 1 c
5 2 d
或者我们可以通过lambda来可爱。
注意:我将字典对齐以根据它们在列表[0, d1, d2]
中的相对位置进行切换。在这种情况下,第一位置是什么都没关系。我任意放置0
。
df.assign(ColB=[*map(lambda x, y: [0, d1, d2][x][y], df.ColA, df.ColB)])
ColA ColB
0 1 a
1 2 f
2 2 e
3 1 b
4 1 c
5 2 d
出于鲁棒性考虑,我会尽量避免可爱,并映射具有默认值功能的lambda
df.assign(ColB=[*map(lambda x, y: {1: d1, 2: d2}.get(x, {}).get(y), df.ColA, df.ColB)])
ColA ColB
0 1 a
1 2 f
2 2 e
3 1 b
4 1 c
5 2 d
答案 2 :(得分:3)
如果需要对许多组进行操作,请使用dict
个dict
中的一个来分别映射每个组。理想情况下,您可以找到一些创建d
的实用方法:
d = {1: d1, 2: d2}
df['ColB'] = pd.concat([gp.ColB.map(d[idx]) for idx, gp in df.groupby('ColA')])
ColA ColB
0 1 a
1 2 f
2 2 e
3 1 b
4 1 c
5 2 d
答案 3 :(得分:1)
我将concat
与reindex
一起使用
idx=pd.MultiIndex.from_arrays([df.ColA, df.ColB])
df.ColB=pd.concat([pd.Series(x) for x in [d1,d2]],keys=[1,2]).reindex(idx).values
df
Out[683]:
ColA ColB
0 1 a
1 2 f
2 2 e
3 1 b
4 1 c
5 2 d
答案 4 :(得分:0)
您可以创建一个针对一个元素执行此操作的函数,然后将 applambda 应用于您的数据框。
def your_func(row):
if row["ColA"] == 1:
return d1[row["ColB"]]
elif row["ColB"] == 2:
return d2[row["ColB"]]
else:
return None
df["ColB"] = df.apply(lambda row: your_func(row), axis=1)
答案 5 :(得分:0)
您可以使用两种替换方式:
df.loc[df['ColA'] == 1,'ColB'] = df['ColB'].replace(d1, regex=True)
df.loc[df['ColA'] == 2,'ColB'] = df['ColB'].replace(d2, regex=True)
我希望它会有所帮助, BR