如何在两个pandas数据帧之间找到共享条目并使用它们在两个数据帧中创建相同的列?

时间:2015-07-24 10:12:51

标签: python pandas dataframe

使用pandas,我创建了两个类似于下面的数据框。

input_df1 = pd.DataFrame({'names':['phone,mobile,cell','boat,ship','car'], 'values':[1,3,3]})
input_df2 = pd.DataFrame({'names':['cell,phone','car,automobile', 'boat'], 'values':[3,7,1]})

enter image description here

我想将'names'列更改为仅包含在两个数据框中找到的名称。目标是让这些名称的值在比较图中自动组合在一起。最终的数据框应该如下所示。

enter image description here

如果两个数据框中都有多个名称可用,则名称不会简化为一个名称,如上面的第0行所示。应该最好删除它们之间没有通用名称的行(但我也可以事先手动完成)。优选地,这也应该在没有for循环的情况下完成,因为实际数据帧超过50k行。

我尝试使用input_df.names.str.contains()input_df.names.isin(),但我无法弄清楚如何在input_df1中找到与input_df2中的名称匹配的名称,比较它们的最短名称,然后用较短的名称替换较长的名称(这是我的思想应该做的)。

1 个答案:

答案 0 :(得分:0)

这是一种策略。

# your data
# =======================================
input_df1 = pd.DataFrame({'names':['phone,mobile,cell','boat,ship','car'], 'values':[1,3,3]})
input_df1

               names  values
0  phone,mobile,cell       1
1          boat,ship       3
2                car       3

input_df2 = pd.DataFrame({'names':['cell,phone','car,automobile', 'boat'], 'values':[3,7,1]})
input_df2

            names  values
0      cell,phone       3
1  car,automobile       7
2            boat       1

我们首先将平面名称记录转换为堆积名称记录。

# groupby-tostack function
# ===============================
def func(group):
     return pd.Series(group['names'].values[0].split(','))

stacked_names1 = input_df1.groupby(level=0).apply(func)
stacked_names1

0  0     phone
   1    mobile
   2      cell
1  0      boat
   1      ship
2  0       car
dtype: object

stacked_names2 = input_df2.groupby(level=0).apply(func)
stacked_names2

0  0          cell
   1         phone
1  0           car
   1    automobile
2  0          boat
dtype: object

接下来,使用np.intersec1d获取常用名称。

common_names = np.intersect1d(stacked_names1, stacked_names2)
common_names

array(['boat', 'car', 'cell', 'phone'], dtype=object)

使用.isin保留有效名称。

stacked_names1.isin(common_names)

0  0     True
   1    False
   2     True
1  0     True
   1    False
2  0     True
dtype: bool

最后,再次通过外层索引上的groupby将堆叠记录转换回平面记录。

def func2(group):
    return pd.Series(','.join(group.values.tolist()))

input_df1['names'] = stacked_names1[stacked_names1.isin(common_names)].groupby(level=0).apply(func2).values
input_df1

        names  values
0  phone,cell       1
1        boat       3
2         car       3

input_df2['names'] = stacked_names2[stacked_names2.isin(common_names)].groupby(level=0).apply(func2).values
input_df2

        names  values
0  cell,phone       3
1         car       7
2        boat       1