我的df如下所示。
key val
0 A1 [1, 2, 3, 4]
1 A2 [1, 2, 7, 9]
2 A3 [1, 3, 5]
3 A4 [6, 9]
4 A5 [8]
我想创建一个名为common的新列,其中包含与我当前键具有相同值的其他键。最终的数据帧如下所示:
key val common
0 A1 [1, 2, 3, 4] {'A2':[1, 2], 'A3':[1, 3]}
1 A2 [1, 2, 7, 9] {'A1':[1, 2], 'A3':[1], 'A4':[9], 'A5':[7]}
2 A3 [1, 3, 5] {'A1':[1, 3], 'A2':[1]}
3 A4 [6, 9] {'A2':[9]}
4 A5 [8] {}
我能想到的唯一方法是创建一个带有空字典的列,然后有两个循环来获取结果。我想知道是否有简单的方法可以做到这一点。
谢谢
答案 0 :(得分:3)
这里是先使用explode
然后使用merge
的一种方法
s=df.explode('Val')
s=s.merge(s,on='Val').query('Key_x ! = Key_y').groupby(['Key_x','Key_y']).Val.apply(list)
l=[y.reset_index(level=0,drop=True).to_dict()for x , y in s.groupby(level=0)]
Out[73]:
[{'A2': [1, 2], 'A3': [1, 3]},
{'A1': [1, 2], 'A3': [1], 'A4': [9], 'A5': [7]},
{'A1': [1, 3], 'A2': [1]},
{'A2': [9]},
{'A2': [7]}]
df['common']=l
更新
l={x: y.reset_index(level=0,drop=True).to_dict()for x , y in s.groupby(level=0)}
df['common']=pd.Series(l).reindex(df.Key).values
答案 1 :(得分:0)
我假设 val 列的每个元素都包含一个字符串
由[
,一个数字列表(用逗号分隔)和]
组成,
就像您可以从Excel文件中读取它一样。
第一步是将 val 列从字符串转换为集合 由基础列表组成:
val2 = df.val.apply(lambda xx: set(eval(xx)))
第二步是计算一个带有交叉点的 Numpy 正方形数组 这些集合(各有一套)和“清除”对角元素中的一个:
comm = val2[np.newaxis, :] & val2[:, np.newaxis]
np.fill_diagonal(comm, set())
第三步是使用 index 和 从 df.key 提取的列:
ind = df.key.values
df2 = pd.DataFrame(data=comm, index=ind, columns=ind)
对于您的样本数据,结果为:
A1 A2 A3 A4 A5
A1 {} {1, 2} {1, 3} {1} {}
A2 {1, 2} {} {1} {1, 9} {7}
A3 {1, 3} {1} {} {1} {}
A4 {1} {1, 9} {1} {} {}
A5 {} {7} {} {} {}
然后定义一个函数,该函数将很快应用于此表的每一行:
def commList(row):
return { k: list(v) for k, v in row.iteritems() if len(v) > 0 }
下一步是应用此功能:
common = df2.apply(commList, axis=1).rename('common')
结果是:
A1 {'A2': [1, 2], 'A3': [1, 3], 'A4': [1]}
A2 {'A1': [1, 2], 'A3': [1], 'A4': [1, 9], 'A5': [7]}
A3 {'A1': [1, 3], 'A2': [1], 'A4': [1]}
A4 {'A1': [1], 'A2': [1, 9], 'A3': [1]}
A5 {'A2': [7]}
Name: common, dtype: object
最后一步是合并 df 和 common 并将其保存回去 放入 df :
df = pd.merge(df, common, left_on='key', right_index=True)