python - 根据两列的比较从第二个 DataFrame 添加列

标签 python pandas dataframe join merge

简单来说,我正在尝试将列 latitudelongitudedf1 添加到名为 df2 通过比较它们的 air_idhpg_id 列的值:

enter image description here

latitudelongitude 添加到 df2 的技巧取决于如何与 df1 进行比较,这可能是 3 种情况之一:

  • df2.air_iddf1.air_hd 匹配时;
  • df2.hpg_iddf1.hpg_hd 匹配时;
  • 当两者匹配时:[df2.air_id, df2.hpg_id] AND [df1.air_hd, df1.hpg_id];

考虑到这一点,预期结果应该是:

enter image description here

请注意 df1 中的 ignore_me 列如何被排除在生成的 DataFrame 之外。

这是设置数据帧的代码:

data = { 'air_id'     : [ 'air1',     '', 'air3', 'air4', 'air2', 'air1' ], 
         'hpg_id'     : [ 'hpg1', 'hpg2',     '', 'hpg4',     '',     '' ], 
         'latitude'   : [  101.1,  102.2,    103,    104,    102, 101.1, ],
         'longitude'  : [     51,     52,     53,     54,     52,    51, ],
         'ignore_me'  : [     91,     92,     93,     94,     95,    96 ] }

df1 = pd.DataFrame(data)
display(df1)


data2 = { 'air_id'    : [     '',  'air2', 'air3', 'air1' ], 
          'hpg_id'    : [ 'hpg1',  'hpg2',     '',     '' ]  }

df2 = pd.DataFrame(data2)
display(df2)

不幸的是,我没有使用 merge() 来完成这项任务。我当前的结果是一个 DataFrame,其中 df1 中的所有列大部分都填充了 NaN:

enter image description here

如何使用上述规则从 df1 复制这些特定列?

最佳答案

使用 sets 和 Numpy broadcasting 来处理东西的匹配......撒上仙尘

ids = ['air_id', 'hpg_id']
cols = ['latitude', 'longitude']

def true(s): return s.astype(bool)

s2 = df2.stack().loc[true].groupby(level=0).apply(set)
s1 = df1[ids].stack().loc[true].groupby(level=0).apply(set)

i, j = np.where((s1.values & s2.values[:, None]).astype(bool))

a = np.zeros((len(df2), 2), int)
a[i, :] = df1[cols].values[j]

df2.join(pd.DataFrame(a, df2.index, cols))

  air_id hpg_id  latitude  longitude
0          hpg1       101         51
1   air2   hpg2       102         52
2   hpg3              103         53

详细信息

s2 看起来像这样

0          {hpg1}
1    {air2, hpg2}
2          {hpg3}
dtype: object

s1

0    {air1, hpg1}
1          {hpg2}
2          {hpg3}
3    {air4, hpg4}
4          {air2}
dtype: object

重点是我们想找出该行中的任何内容是否与其他数据框中一行中的其他内容相匹配。现在我可以使用广播和 &

s1.values & s2.values[:, None]

array([[{'hpg1'}, set(), set(), set(), set()],
       [set(), {'hpg2'}, set(), set(), {'air2'}],
       [set(), set(), {'hpg3'}, set(), set()]], dtype=object)

但是空集在 bool 上下文中计算为 False 所以

(s1.values & s2.values[:, None]).astype(bool)

array([[ True, False, False, False, False],
       [False,  True, False, False,  True],
       [False, False,  True, False, False]], dtype=bool)

现在我可以使用 np.where 告诉我这些 True 在哪里

i, j = np.where((s1.values & s2.values[:, None]).astype(bool))

print(i, j)

[0 1 1 2] [0 1 4 2]

这些分别是来自 df2df1 的行。但我不需要两行 1,所以我创建了一个适当大小的空数组,期望我将覆盖行 1。我用 df1

中的纬度和经度填充这些值
a = np.zeros((len(df2), 2), int)
a[i, :] = df1[cols].values[j]

a

array([[101,  51],
       [102,  52],
       [103,  53]])

然后我将其包装在一个 pd.DataFrame 中并如上所示加入。

关于python - 根据两列的比较从第二个 DataFrame 添加列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49329997/

相关文章:

python - Django,SQLite - 带重音字母的字符串的准确排序

python - 使用 matplotlib 绘制 semilogx,然后将其转换为 Bokeh

python - Django 关于对象保存事件

python - 第一次写入 CSV 文件后跳过标题(Python)

r - 删除重复的 id 和条件的子集

python - 如何在分组依据后检查列是否包含特定元素?

python - 有没有更优雅的方式在 Python 中引发错误?[具体案例]

pandas - 将列添加到日期时间驱动的 Groupby 函数

python - 如何从 df 中删除特定年份

python - Pandas 数据框基于日期范围的条件累积和