【问题标题】:Python Pandas - merge rows if some values are blankPython Pandas - 如果某些值为空白,则合并行
【发布时间】:2017-04-05 15:04:36
【问题描述】:

我有一个看起来有点像这样的数据集:

ID   Name            Address      Zip    Cost
1    Bob the Builder 123 Main St  12345  
1    Bob the Builder                     $99,999.99
2    Bob the Builder 123 Sub St   54321  $74,483.01
3    Nigerian Prince Area 51      33333  $999,999.99
3    Pinhead Larry   Las Vegas    31333  $11.00
4    Fox Mulder      Area 51             $0.99

缺少数据是可以的,除非它们很明显可以合并。我的意思是代替上面的数据集,我想合并ID和Name相同的行,并且其他特征可以互相填补空白。例如,上面的数据集将变为:

ID   Name            Address      Zip    Cost
1    Bob the Builder 123 Main St  12345  $99,999.99
2    Bob the Builder 123 Sub St   54321  $74,483.01
3    Nigerian Prince Area 51      33333  $999,999.99
3    Pinhead Larry   Las Vegas    31333  $11.00
4    Fox Mulder      Area 51             $0.99

我考虑过使用df.groupby(["ID", "Name"]),然后将字符串连接起来,因为缺失的值是空字符串,但没有成功。

数据已从网站上删除,因此它们必须经过大量清理才能最终到达这里。我想不出一种优雅的方式来解决这个问题!

【问题讨论】:

    标签: python pandas dataframe duplicates


    【解决方案1】:

    我将描述一个算法:

    1. 将填充了所有字段的所有行放在一边。我们不需要接触这些。
    2. 创建一个类似于输入的布尔数据框,其中空字段为 False,填充字段为 True。这是df.notnull()
    3. 对于df.Name.unique() 中的每个名称:
      1. df[df.Name == name] 作为工作集。
      2. 对每对(或元组)布尔行求和,得到一个与输入列宽度相同的布尔向量,但始终填充的列除外。在示例中,这表示[True, True, False][False, False, True],因此总和为[1, 1, 1]
      3. 如果总和在所有地方都等于 1,则可以合并该对(或元组)行。

    但是这里有很多可能的边缘情况,例如如果您有三行 A、B、C 并且您可以合并 A+B 或 A+C,该怎么办。如果您可以在实施合并算法之前缩小数据中存在的约束范围,将会有所帮助。

    【讨论】:

    • 非常感谢!当我在数据帧上执行 groupby() 时,我也注意到了这种模式,但并不真正知道如何处理它。而且我应该澄清限制 - 边缘情况已经得到处理,所以它只有 2 行的集合,像这样重复。
    【解决方案2】:

    这仅在我们可能合并的行彼此相邻时才有效。

    设置

    df = pd.DataFrame(dict(
            ID=[1, 1, 2, 3, 3, 4],
            Name=['Bob the Builder'] * 3 + ['Nigerian Prince', 'Pinhead Larry', 'Fox Mulder'],
            Address=['123 Main St', '', '123 Sub St', 'Area 51', 'Las Vegas', 'Area 51'],
            Zip=['12345', '', '54321', '33333', '31333', ''],
            Cost=['', '$99,999.99', '$74,483.01', '$999.999.99', '$11.00', '$0.99']
        ))[['ID', 'Name', 'Address', 'Zip', 'Cost']]
    

    补缺
    replace('', np.nan) 然后前向填充再后向填充

    df_ = df.replace('', np.nan).ffill().bfill()
    

    连接
    如果是重复行,则取最后一行填满的 df_
    如果不重复,则取非填满df

    pd.concat([
            df_[df_.duplicated()],
            df.loc[df_.drop_duplicates(keep=False).index]
        ])
    

    【讨论】:

      猜你喜欢
      • 2015-10-10
      • 1970-01-01
      • 2013-08-01
      • 1970-01-01
      • 2018-06-17
      • 1970-01-01
      • 1970-01-01
      • 2019-12-09
      相关资源
      最近更新 更多