【问题标题】:Pandas: df.groupby() is too slow for big data set. Any alternatives methods?Pandas:df.groupby() 对于大数据集来说太慢了。有什么替代方法吗?
【发布时间】:2017-11-26 00:46:19
【问题描述】:

我有一个包含 380 万行和一列的 pandas.DataFrame,我正在尝试按索引对它们进行分组。

索引是客户 ID。我想按索引对qty_liter 进行分组:

df = df.groupby(df.index).sum()

但是完成计算需要很长时间。有没有其他方法可以处理非常大的数据集?

这里是df.info()

<class 'pandas.core.frame.DataFrame'>
Index: 3842595 entries, -2147153165 to \N
Data columns (total 1 columns):
qty_liter    object
dtypes: object(1)
memory usage: 58.6+ MB

数据如下:

【问题讨论】:

  • 将索引保存为第一列,然后终端中的这一行将实现您想要的awk 'BEGIN{FS=OFS=","}{a[$1]+=$2}END{ for (i in a) print i,a[i]}'
  • 您有多少个独特的组?即使有 380 万个唯一索引,它也能在不到一秒的时间内计算总和(我尝试使用浮点数)。
  • 你关心输出数据框中的索引信息吗? qty_liter中会不会有负值?
  • 是的,索引是消费者的身份证号码。所以我想将qty_liter按消费者的ID分组。我检查了qty_liter的值,都是正数和浮点数。
  • 问题是索引和列值都不是数字——我会检查你创建这个框架的方式

标签: python pandas grouping bigdata


【解决方案1】:

问题在于您的数据不是数字。处理字符串比处理数字需要更长的时间。先试试这个:

df.index = df.index.astype(int)
df.qty_liter = df.qty_liter.astype(float)

然后再次执行groupby()。它应该快得多。如果是,请查看是否可以修改数据加载步骤以从一开始就拥有正确的数据类型。

【讨论】:

  • 分类词怎么样,这会提高速度吗?
  • 分类没问题,只要分类的数量不是很大。
【解决方案2】:

您的数据分类太多,这是导致groupby 代码太慢的主要原因。我尝试使用 Bodo 来查看它如何处理大型数据集上的 groupby。我使用常规的顺序 Pandas 和并行化的 Bodo 运行代码。 Pandas 用了大约 20 秒,Bodo 只用了 5 秒。 Bodo 基本上会自动并行化您的 Pandas 代码,并允许您在多个处理器上运行它,这是原生 pandas 无法做到的。最多可免费使用四个内核:https://docs.bodo.ai/latest/source/installation_and_setup/install.html

数据生成注意事项:我生成了一个比较大的数据集,有 2000 万行和 18 个数值列。为了使生成的数据更类似于您的数据集,添加了另外两个名为“index”和“qty_liter”的列。

#data generation

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(20000000, 18), columns = list('ABCDEFGHIJKLMNOPQR'))
df['index'] = np.random.randint(2147400000,2147500000,20000000).astype(str)
df['qty_liter'] = np.random.randn(20000000)

df.to_parquet("data.pq")

使用普通熊猫:

import time
import pandas as pd
import numpy as np

start = time.time()
df = pd.read_parquet("data.pq")
grouped = df.groupby(['index'])['qty_liter'].sum()
end = time.time()
print("computation time: ", end - start)
print(grouped.head())

output:
computation time:  19.29292106628418
index
2147400000    29.701094
2147400001    -7.164031
2147400002   -21.104117
2147400003     7.315127
2147400004   -12.661605
Name: qty_liter, dtype: float64

与博多:

%%px

import numpy as np
import pandas as pd
import time
import bodo

@bodo.jit(distributed = ['df'])
def group_by():
    start = time.time()
    df = pd.read_parquet("data.pq")
    df = df.groupby(['index'])['qty_liter'].sum()
    end = time.time()
    print("computation time: ", end - start)
    print(df.head())
    return df
    
df = group_by()

output:
[stdout:0] 
computation time:  5.12944599299226
index
2147437531     6.975570
2147456463     1.729212
2147447371    26.358158
2147407055    -6.885663
2147454784    -5.721883
Name: qty_liter, dtype: float64

免责声明:我是在 Bodo.ai 工作的数据科学家倡导者

【讨论】:

  • Bodo 链接失效
  • 现已修复!谢谢你告诉我!
【解决方案3】:

我不使用字符串,而是定义组的整数值。仍然很慢:大约 3 分钟,而在 Stata 中只有几分之一秒。观测数约为113k,x、y、z定义的组数约为26k。

a= df.groupby(["x", "y", "z"])["b"].describe()[['max']]

x,y,z:整数值

b:真实价值

【讨论】:

  • 这是一个答案还是另一个问题?
猜你喜欢
  • 2011-04-10
  • 2012-06-16
  • 1970-01-01
  • 2016-05-28
  • 1970-01-01
  • 1970-01-01
  • 2011-10-17
  • 2013-05-01
  • 2021-10-18
相关资源
最近更新 更多