【问题标题】:How to groupby join rows while ignoring None values in columns?如何在忽略列中的无值的同时分组连接行?
【发布时间】:2020-01-22 01:07:14
【问题描述】:

我有一个如下所示的数据框,

df = pd.DataFrame(np.array([['a', 'a', 'b', 'b'], [1, 1, 2, 2], 
                            ['k', 'l', 'm', 'n']]).T, 
                  columns=['a', 'b', 'c'])

df = df.groupby(['a'])['b', 'c'].agg(','.join)

print(df)

     b     c
a       
a   1,1   k,l
b   2,2   m,n

但是当我将 None 值添加到原始数据帧时,相同的 agg func 返回不同的结果,即。

df = pd.DataFrame(np.array([['a', 'a', 'b', 'b'], [1, 1, 2, 2], 
                            ['k', 'l', 'm', None]]).T, 
                  columns=['a', 'b', 'c'])

df = df.groupby(['a'])['b', 'c'].agg(','.join)

print(df)

      b       c
a       
a   a,b,c   a,b,c
b   a,b,c   a,b,c

对于第二个数据帧,即在一行中没有值,我正在寻找低于所需输出的这个:

     b     c
a       
a   1,1   k,l
b   2,2   m

【问题讨论】:

  • 尝试用 np.nan 或 ' ' 替换 None。 Pandas 不适用于 None。
  • 能否插入'' 而不是None?当使用'' 超过None 时,结果是m,
  • @jasonwong 我试过了,但仍然没有得到我想要的输出。
  • @user_12 我试过了请准确地分享你改变了什么,发生了什么。
  • 您能否首先解释一下该操作的目的是什么?这似乎有些不寻常。

标签: python pandas


【解决方案1】:

您也可以在 lambda 中使用 dropna。万一你的数据框有任何非字符串列,你应该在dropna之后链接额外的.astype(str)。如果您确定所有列值都是字符串,则只需跳过 .astype(str) 部分

df_join = df.groupby('a').agg(lambda x: ','.join(x.dropna().astype(str)))

Out[809]:
     b    c
a
a  1,1  k,l
b  2,2    m

更快一点的解决方案是使用python filter 过滤掉Nonemapjoin 之前转换为字符串。正如我所说,它在大数据帧上要快一点,但折衷的可读性较差

df_join = df.groupby('a').agg(lambda x: ','.join(map(str, filter(None,x))))

Out[823]:
     b    c
a
a  1,1  k,l
b  2,2    m

【讨论】:

    【解决方案2】:

    一种使用lambda过滤None的方法:

    df = df.groupby('a').agg(lambda x: ','.join(str(i) for i in x if i is not None))
    print(df)
    

    输出:

         b    c
    a          
    a  1,1  k,l
    b  2,2    m
    

    【讨论】:

    • 谢谢。它是否可扩展,因为我正在处理庞大的数据集。就我而言,性能很重要。
    【解决方案3】:

    另一种方法是使用: more_itertools.chunked(iterable, n) 方法: https://more-itertools.readthedocs.io/en/stable/api.html#grouping

    【讨论】:

      【解决方案4】:

      我根据上面的评论修改并测试它,现在它可以工作了:

      df = pd.DataFrame(np.array([['a', 'a', 'b', 'b'], [1, 1, 2, 2], 
                                  ['k', 'l', 'm', None]]).T, 
                        columns=['a', 'b', 'c'])
      df = df.replace([None], '')
      df.b = df.b.astype('str')
      df = df.groupby(['a'])['b', 'c'].agg(lambda x:','.join(x).rstrip(','))
      print(df)
      

      输出:

           b    c
      a          
      a  1,1  k,l
      b  2,2    m
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-06-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-09
        • 1970-01-01
        相关资源
        最近更新 更多