【问题标题】:Creating new column in pandas dataframe with a list of values from another column without using "groupby"在不使用“groupby”的情况下使用来自另一列的值列表在 pandas 数据框中创建新列
【发布时间】:2016-04-08 03:59:45
【问题描述】:

我使用大型数据集,使 pandas 的 group 和 groupby 函数需要很长时间/占用太多内存。我听说有些人说 groupby 可能很慢,但是很难找到更好的解决方案。

如果我的数据框有 2 列类似于:

df = pd.DataFrame({'a':[1,2,2,4], 'b':[1,1,1,1]})

a     b     
1     1     
2     1     
2     1      
4     1     

我希望返回与另一列中的值匹配的值列表:

a     b     list_of_b
1     1        [1]
2     1        [1,1]
2     1        [1,1]
4     1        [1]

我目前使用:

df_group = df.groupby('a')
df['list_of_b'] = df.apply(lambda row: df_group.get_group(row['a'])['b'].tolist(), axis=1)

上面的代码适用于小东西,但不适用于大型数据帧(df > 1,000,000 行)有没有人有更快的方法来做到这一点?

【问题讨论】:

  • 创建值列表是有问题的,因为 pandas 想要将其转换为系列并在索引上对齐,您可以尝试df['list_of_b'] = df['a'].map(df.groupby('a')['b'].apply(list)) 以提高速度

标签: python pandas


【解决方案1】:

我能想到的最短解决方案:

df = pd.DataFrame({'a':[1,2,2,4], 'b':[1,1,1,1]})
df.join(pd.Series(df.groupby(by='a').apply(lambda x: list(x.b)), name="list_of_b"), on='a')

   a  b    list_of_b
0  1  1     [1]
1  2  1  [1, 1]
2  2  1  [1, 1]
3  4  1     [1]

【讨论】:

    【解决方案2】:

    在 4K 行 df 上,我得到以下信息:

    In [29]:
    df_group = df.groupby('a')
    ​
    %timeit df.apply(lambda row: df_group.get_group(row['a'])['b'].tolist(), axis=1)
    %timeit df['a'].map(df.groupby('a')['b'].apply(list))
    
    1 loops, best of 3: 4.37 s per loop
    100 loops, best of 3: 4.21 ms per loop
    

    【讨论】:

      【解决方案3】:

      只是进行分组,然后加入原始数据帧似乎要快一些:

      def make_lists(df):
          g = df.groupby('a')
          def list_of_b(x):
              return x.b.tolist()
          return df.set_index('a').join(
              pd.DataFrame(g.apply(list_of_b),
                           columns=['list_of_b']),
              rsuffix='_').reset_index()
      

      这给了我 192ms 每个循环 1M 行生成如下:

      df1 = pd.DataFrame({'a':[1,2,2,4], 'b':[1,1,1,1]})
      low = 1
      high = 10 
      size = 1000000
      df2 = pd.DataFrame({'a':np.random.randint(low,high,size),
                          'b':np.random.randint(low,high,size)})
      
      make_lists(df1)
      Out[155]:
          a   b   list_of_b
      0   1   1   [1]
      1   2   1   [1, 1]
      2   2   1   [1, 1]
      3   4   1   [1]
      In [156]:
      
      
      %%timeit
      make_lists(df2)
      10 loops, best of 3: 192 ms per loop
      

      【讨论】:

        猜你喜欢
        • 2018-03-14
        • 2021-08-19
        • 2018-02-26
        • 2020-06-15
        • 1970-01-01
        • 2023-01-17
        • 2019-08-18
        • 2018-12-10
        • 1970-01-01
        相关资源
        最近更新 更多