【问题标题】:How to merge mostly duplicated rows如何合并大部分重复的行
【发布时间】:2013-06-05 01:57:15
【问题描述】:

我的一些数据看起来像:

date, name, value1, value2, value3, value4
1/1/2001,ABC,1,1,,
1/1/2001,ABC,,,2,
1/1/2001,ABC,,,,35

我正在努力达到我可以跑步的程度

data.set_index(['date', 'name'])

但是,在数据原样的情况下,当然有重复项(如上所示),所以我不能这样做(而且我不想要一个有重复项的索引,我不能简单地 drop_duplicates( ),因为这会丢失数据)。

我希望能够将具有相同 [日期,名称] 值的行强制为单行,前提是它们可以基于某些值为 NaN 的值成功收敛(类似于 combine_first() 的行为)。例如,上述内容将结束于

date, name, value1, value2, value3, value4
1/1/2001,ABC,1,1,2,35

如果两个值不同且一个不是 NaN,则这两行不应收敛(这可能是我需要跟进的错误)。

(为了扩展上面的例子,实际上可能有任意数量的行——给定任意数量的列——应该能够收敛到一行。)

这感觉像是一个应该可以通过 pandas 解决的问题,但我无法找到一个优雅的解决方案。

【问题讨论】:

    标签: python duplicates pandas dataframe


    【解决方案1】:

    假设您有一些函数combine_it,给定一组具有重复值的行,它返回单行。首先,按datename 分组:

    grouped = data.groupby(['date', 'name'])
    

    然后只需应用聚合函数,boom就大功告成了:

    result = grouped.agg(combine_it)
    

    您还可以通过传递agg 一个dict,为不同的列提供不同的聚合函数。

    【讨论】:

    • 谢谢,这肯定会减少关键步骤。有没有特别有效的习语可以做到这一点?根据我的经验(以及使用您的建议进行的初始测试), .agg() 可能会导致执行速度非常慢(可能不足为奇)。也许是不可避免的?
    • 也许吧?您可以尝试使用内置的 numpy 函数(“sum”、“max”等)来加快速度(使用 cythonized 函数)。这可能超出了 groupby 的正常用例,因为相对于 DataFrame 的总大小,您最终可能会得到许多组。
    • 好吧,除非有另一个答案,至少我知道我没有错过任何太明显的东西......
    • @severian 是的,combine_it 是慢而不是 agg。
    【解决方案2】:

    如果您没有数字字段值,则使用 count、min、sum 等进行聚合既不可能也不明智。尽管如此,您仍可能希望根据一个或多个主键将重复记录折叠为单个记录(例如)。

    # Firstly, avoid Nan values in the columns you are grouping on!
    df[['col1', 'col2']] =  df[['col1', 'col2']].fillna('null')
    
    
      # Define your own customized operation in pandas agg() function
    df = df.groupby(['col1', 'col2']).agg({'SEARCH_TERM':lambda x: ', '.join(tuple(x.tolist())),
    
                                         'HITS_CONTENT':lambda x: ', '.join(tuple(x.tolist()))}
                                       )
    

    按一列或多列分组并折叠值,首先将它们转换为列表,然后转换为元组,最后转换为字符串。如果您愿意,您也可以将它们作为列表或元组存储在每个字段中,或者与 agg 一起应用。函数和字典对不同列的操作非常不同。

    【讨论】:

      【解决方案3】:

      由于您的列值不会重复,因此您可以使用 agg 函数的技巧,如下所示:

      data.groupby(['date', 'name']).agg('sum')
      

      【讨论】:

        【解决方案4】:
        df1 = df.groupby(["date", "name"])
        df1 = df1.apply(lambda x: x.ffill().bfill()).drop_duplicates()
        print(df1.head())
        
               date name  value1  value2  value3  value4
        0  1/1/2001  ABC     1.0     1.0     2.0    35.0
        

        根据这个答案:https://stackoverflow.com/a/45599151/1154981

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-02-14
          • 1970-01-01
          • 1970-01-01
          • 2022-01-02
          • 1970-01-01
          • 2013-08-19
          • 2020-04-17
          相关资源
          最近更新 更多