我需要根据第二个数据帧的属性向现有的pandas数据框添加一列。我做了一个很小的例子来说明我的确切要求。
我有两个数据框,一个代表一对名字,另一个代表两个人之间的互动:
>>> names
id_a id_b
0 ben jack
1 jack ben
2 jill amir
3 wilma jill
4 amir wilma
>>> interactions
individual1 individual2
0 jill jack
1 jack jill
2 wilma jill
3 amir jill
4 amir jack
5 jack amir
6 jill amir
我需要的基本上是这样的:对于names
中的每对名称,我需要计算这两个名称之间的交互次数,因此interactions
中的行数{ {1}}是names['id_a']
或interactions['individual1']
,interactions['individual2']
是names['id_b']
或interactions['individual1']
。对于名称中的所有行,此计数需要包含在列interactions['individual2']
中,即使名称是重复的(即,如果有一行,其中id_a是ben,id_b是jack,而行是其中的名称是反转(id_a是jack,id_b是ben),这两行都应该包括num_interactions)
结果数据框如下所示:
num_interactions
这很好用,但它很难看,难以阅读,效率低下,而且我知道必须有更好的方法!也许有某种合并,但我真的不知道如何使用复杂的标准......
>>> names
id_a id_b num_interactions
0 ben jack 0.0
1 jack ben 0.0
2 jill amir 2.0
3 wilma jill 1.0
4 amir wilma 0.0
enter code here
如果你想玩这个,你可以使用它来重现我上面的虚拟数据帧。
for i in range(len(names)):
names.loc[i, 'num_interactions'] = len(
interactions[((interactions['individual1'] == names.loc[i, 'id_a']) &
(interactions['individual2'] == names.loc[i, 'id_b'])) |
((interactions['individual2'] == names.loc[i, 'id_a']) &
(interactions['individual1'] == names.loc[i, 'id_b']))
])
提前致谢!
答案 0 :(得分:1)
假设顺序无关紧要,您可以按列对每个数据框进行排序。对于第二个数据框,使用groupby
+ count
计算每组互动,然后对结果和第一个数据框执行左外merge
。
i = pd.DataFrame(np.sort(names, axis=1))
j = pd.DataFrame(np.sort(interactions, axis=1))
k = j.groupby(j.columns.tolist())[0].count().reset_index(name='count')
df = i.merge(k, on=[0, 1], how='left')\
.fillna(0)\
.rename(columns={0 : 'id_a', 1 : 'id_b'})
df.iloc[:, :2] = names.values
df
id_a id_b count
0 ben jack 0.0
1 ben jack 0.0
2 amir jill 2.0
3 jill wilma 1.0
4 amir wilma 0.0
答案 1 :(得分:1)
对不起,我添加新列等有点难看,但你可以得到这个想法并改进它...... 首先,我假设名称中的所有对都是唯一的。所以我给每一对一个ID
names_ids = pd.DataFrame(pd.concat([names.iloc[:, 0] + '-' + names.iloc[:, 1],
names.iloc[:, 1] + '-' + names.iloc[:, 0]],
axis=0),
columns=['pair'])
names_ids['id'] = names_ids.index
names_ids.index = names_ids.pair
然后我将这些id加入到交互中,我再次在交互中翻转每一对
interactions_new = pd.DataFrame(pd.concat([interactions.iloc[:, 0] + '-' + interactions.iloc[:, 1],
interactions.iloc[:, 1] + '-' + interactions.iloc[:, 0]],
axis=0),
columns=['pair'])
interactions_new['count'] = np.ones(len(interactions_new))
count_id = interactions_new.join(names_ids['id'], on='pair', how='left').groupby('id').count().loc[:, ['count']]
count_id['id'] = count_id.index
所以最后我只计算交互中的每个id:
names_ids.index = names_ids.id
result = count_id.join(names_ids.pair.iloc[:len(names_ids)/2], on='id', how='left')
result['count'] /= 2
print result
丑陋,但没有for循环,我得到:
count id pair
id
2.0 2 2.0 jill-amir
3.0 1 3.0 wilma-jill