【问题标题】:Pandas groupby with custom function to return the column values as an array带有自定义函数的 Pandas groupby 将列值作为数组返回
【发布时间】:2020-04-19 03:50:43
【问题描述】:

我一定是做错了什么,但即使经过重大试验,我也无法弄清楚我做错了什么......

数据:

df = pd.DataFrame({
    'ID': [3,3,3,2,2,2,1,1],
    'X': [10,11,12,20,21,30,31,32],
    'Y': [100,110,120,200,210,300,310,320]
})

# Outputs:
   ID   X    Y
0   3  10  100
1   3  11  110
2   3  12  120
3   2  20  200
4   2  21  210
5   2  30  300
6   1  31  310
7   1  32  320

这是我的聚合函数。 (逗号分隔值工作正常)

def _colum_to_array(data):
    # data['Xs'] = ",".join(str(d) for d in data['X']) # works
    # data['Ys'] = ",".join(str(d) for d in data['Y']) # works

    # Next two lines causes this: Length of values does not match length of index
    # which kind of make sense.
    # data['Xs'] = [data['X'].values] 
    # data['Ys'] = [data['Y'].values] 

    # but why is this not working
    # np.tile is generating same number of array data
    data['Xs'] = np.tile([data['X'].values], (data.shape[0], 1))
    data['Ys'] = np.tile([data['Y'].values], (data.shape[0], 1))

    return data

这就是我的分组方式:

df = df.groupby(['ID']).apply(_colum_to_array)

## Output is:
   ID   X    Y  Xs  Ys
0   3  10  100  10  10
1   3  11  110  10  10
2   3  12  120  10  10
3   2  20  200  20  20
4   2  21  210  20  20
5   2  30  300  20  20
6   1  31  310  31  31
7   1  32  320  31  31

我期待或试图得到的是这样的。 X/Y 列的值被捕获为数组的位置

   ID   X    Y  Xs          Ys
0   3  10  100  [10,11,12]  [100,110,120]
1   3  11  110  [10,11,12]  [100,110,120]
2   3  12  120  [10,11,12]  [100,110,120]
3   2  20  200  [20,21,30]  [200,210,300]
4   2  21  210  [20,21,30]  [200,210,300]
5   2  30  300  [20,21,30]  [200,210,300]
6   1  31  310  [31,32]     [310,320]
7   1  32  320  [31,32]     [310,320]

【问题讨论】:

    标签: python pandas group-by aggregate


    【解决方案1】:

    使用groupby.aggmerge 作为:

    df_new = df.merge(df.groupby("ID", as_index=False).agg(list)\
               .rename(columns={'X':'Xs','Y':'Ys'}))
    #or with pandas 1.0.1 you can do
    df_new = df.merge(df.groupby("ID").agg(Xs=('X',list), Ys=('Y',list)).reset_index())
    
    print(df_new)
       ID   X    Y            Xs               Ys
    0   3  10  100  [10, 11, 12]  [100, 110, 120]
    1   3  11  110  [10, 11, 12]  [100, 110, 120]
    2   3  12  120  [10, 11, 12]  [100, 110, 120]
    3   2  20  200  [20, 21, 30]  [200, 210, 300]
    4   2  21  210  [20, 21, 30]  [200, 210, 300]
    5   2  30  300  [20, 21, 30]  [200, 210, 300]
    6   1  31  310      [31, 32]       [310, 320]
    7   1  32  320      [31, 32]       [310, 320]
    

    【讨论】:

      【解决方案2】:

      您的方法是正确的,但这里的问题是,pandas 通常不能很好地处理对象列(包括列表和类似列表的类型)。它在内部对 numpy 数组进行特殊处理,因此您只能通过首先使用 .tolist() 将其转换为列表来分配列:

      def _colum_to_array(data):
          data['Xs'] = np.tile([data['X'].values], (data.shape[0], 1)).tolist()
          data['Ys'] = np.tile([data['Y'].values], (data.shape[0], 1)).tolist()
      
          return data
      

      然后你的代码就可以工作了:

      df.groupby(['ID']).apply(_colum_to_array)
      
         ID   X    Y            Xs               Ys
      0   3  10  100  [10, 11, 12]  [100, 110, 120]
      1   3  11  110  [10, 11, 12]  [100, 110, 120]
      2   3  12  120  [10, 11, 12]  [100, 110, 120]
      3   2  20  200  [20, 21, 30]  [200, 210, 300]
      4   2  21  210  [20, 21, 30]  [200, 210, 300]
      5   2  30  300  [20, 21, 30]  [200, 210, 300]
      6   1  31  310      [31, 32]       [310, 320]
      7   1  32  320      [31, 32]       [310, 320]
      

      【讨论】:

      • 感谢您解释我失踪的地方。总是很高兴知道额外的信息。
      【解决方案3】:
      x=df.groupby(['ID'])['X'].apply(list).reset_index()
      y=df.groupby(['ID'])['Y'].apply(list).reset_index()
      pd.merge(df,pd.merge(x,y,left_on='ID',right_on='ID'),left_on='ID',right_on='ID',suffixes=['','s'])
      

      解释:“x”将具有列表值“Xs”,“y”将具有列表值“Ys”。现在将这两个数据帧与原始数据帧 df 合并,并为 'x' 和 'y' 添加后缀 's',它们都通过内部合并语句合并为一个

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-10-05
        • 2019-06-08
        • 1970-01-01
        • 2021-06-19
        • 2016-09-21
        • 2017-07-29
        • 1970-01-01
        • 2017-08-04
        相关资源
        最近更新 更多