识别df行之间的公共元素以创建新列

时间:2019-09-10 15:08:32

标签: python pandas numpy dataframe

我的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]            {}

我能想到的唯一方法是创建一个带有空字典的列,然后有两个循环来获取结果。我想知道是否有简单的方法可以做到这一点。
谢谢

2 个答案:

答案 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)
相关问题