我有一本字典,我想使用该字典对df中的新列进行分类。应将df中的Value
列与字典中的值进行比较。 df中的新列应该是与值关联的Key。
d = {'Car':['1','2','3'],
'Chicken legs':['4','5','6'],
'Coronary artery bypass graft surgery':['7','8','9','10','11','12']}
DF
Color Style Value
red round 1
blue square 5
green triangle 9
orange sphere 12
最终df
Color Style Value Thing
red round 1 Car
blue square 5 Chicken legs
green triangle 9 Coronary artery bypass graft surgery
orange sphere 12 Coronary artery bypass graft surgery
我的第一个倾向是把它放到df(df_dict)中,但我无法将df中的单个值与df_dict中的列表进行比较。
df_dict = pd.DataFrame({'Thing':list(d.keys()), 'Values':list(d.values())})
Thing Values
0 Car [1, 2, 3]
1 Chicken_legs [4, 5, 6]
2 Coronary artery bypass graft surgery [7, 8, 9, 10, 11, 12]
以下代码适用于单个元素。然而,我的字典有32个元素,我想有一个更好的方法,而不仅仅是创建下面的32个代码版本。我只是不知道那种做法会是什么。
df.loc[df['Value'].isin(['1', '2', '3]),'Thing']='Car'
是否可以使用字典和isin()
?
我应该将字典转换为列表吗?
答案 0 :(得分:2)
更好的是,反转字典,所以你有类似的东西:
v_map = {
1: 'Car', 2: 'Car', 3: 'Car',
4: 'Chicken legs', 5: 'Chicken legs', 6: 'Chicken legs',
7: 'Coronary artery bypass graft surgery',
...
12: 'Coronary artery bypass graft surgery'
}
现在,您的新专栏只是为新列中的字符串插入v_map[df['Value']]
。
答案 1 :(得分:2)
你可以为此创建一个辅助函数:
In [60]: def argcontains(item):
...: for i, v in d.items():
...: if item in v:
...: return i
...:
然后map
到相应的列:
In [61]: df['thing'] = df.Value.map(argcontains)
In [62]: df
Out[62]:
Value thing
0 1 Car
1 5 Chicken legs
2 9 Coronary artery bypass graft surgery
3 12 Coronary artery bypass graft surgery
这可能稍微更一般(并且避免每次重新计算d.items()
,尽管这很小),例如:
In [73]: def argcontains2(item_iterator, item):
...: for i, v in item_iterator:
...: if item in v:
...: return i
...:
In [74]: from functools import partial
In [75]: argcontains = partial(argcontains2, d.items())
如果您需要经常按值d
引用数据,那么最好创建另一个答案中提到的数据的反向索引(反向字典)。
但是如果你只需要一次反向查找来构造这个列,那么它将使用更少的内存并且需要更少的计算来使用如上所示的简单循环。