从 pandas 数据框中保存的分组数据高效地创建大量直方图
Efficiently creating lots of Histograms from grouped data held in pandas dataframe
我想根据 pandas 数据框中的分组数据创建一堆直方图。这是 a link 一个类似的问题。要生成一些与我正在使用的非常相似的玩具数据,您可以使用以下代码:
from pandas import DataFrame
import numpy as np
x = ['A']*300 + ['B']*400 + ['C']*300
y = np.random.randn(1000)
df = DataFrame({'Letter':x, 'N':y})
我想将这些直方图(读取分箱数据)放入新的数据框中并保存以供以后处理。这是真正的问题,我的文件是 6 GB,有 400k+ 组,只有 2 列。
我考虑过使用简单的 for 循环来完成这项工作:
data=[]
for group in df['Letter'].unique():
data.append(np.histogram(df[df['Letter']==group]['N'],range=(-2000,2000),bins=50,density=True)[0])
df2=DataFrame(data)
请注意,bins、range 和 density 关键字对于我的目的都是必需的,这样直方图在我的新数据帧 df2 中的行之间是一致的和标准化的(参数值来自我的真实数据集,所以它对玩具数据集)。 for 循环效果很好,在玩具数据集上按预期生成 3 行 50 列的 pandas 数据框。在我的真实数据集上,我估计完成代码的时间约为 9 天。有什么 better/faster 方法可以做我正在寻找的事情吗?
P.S。我考虑过多处理,但我认为创建进程和切片数据的开销会比连续 运行 慢(我可能是错的,不介意在这个问题上得到纠正)。
对于您在此处描述的问题类型,我个人通常会执行以下操作,基本上是将整个事情委托给多线程Cython/C++。这需要一些工作,但并非不可能,而且我不确定目前是否真的有可行的替代方案。
以下是构建基块:
首先,您的 df.x.values
、df.y.values
只是 numpy 数组。 This link 展示了如何从此类数组中获取 C 指针。
现在您有了指针,您可以使用 Cython 的 prange
编写一个真正的多线程程序并从这一点开始放弃任何 Python(您现在处于 C++ 领域) .所以假设你有 k 线程扫描你的 6GB 数组,并且线程 i 处理其键具有散列的组 i模k.
对于 C 程序(这就是您的代码现在真正的样子),GNU 科学图书馆有一个 nice histogram module.
当 prange
完成后,您需要将 C++ 结构转换回 numpy 数组,然后再从那里转换回 DataFrame。在 Cython 中包装整个东西,并像普通的 Python 函数一样使用它。
我想根据 pandas 数据框中的分组数据创建一堆直方图。这是 a link 一个类似的问题。要生成一些与我正在使用的非常相似的玩具数据,您可以使用以下代码:
from pandas import DataFrame
import numpy as np
x = ['A']*300 + ['B']*400 + ['C']*300
y = np.random.randn(1000)
df = DataFrame({'Letter':x, 'N':y})
我想将这些直方图(读取分箱数据)放入新的数据框中并保存以供以后处理。这是真正的问题,我的文件是 6 GB,有 400k+ 组,只有 2 列。
我考虑过使用简单的 for 循环来完成这项工作:
data=[]
for group in df['Letter'].unique():
data.append(np.histogram(df[df['Letter']==group]['N'],range=(-2000,2000),bins=50,density=True)[0])
df2=DataFrame(data)
请注意,bins、range 和 density 关键字对于我的目的都是必需的,这样直方图在我的新数据帧 df2 中的行之间是一致的和标准化的(参数值来自我的真实数据集,所以它对玩具数据集)。 for 循环效果很好,在玩具数据集上按预期生成 3 行 50 列的 pandas 数据框。在我的真实数据集上,我估计完成代码的时间约为 9 天。有什么 better/faster 方法可以做我正在寻找的事情吗?
P.S。我考虑过多处理,但我认为创建进程和切片数据的开销会比连续 运行 慢(我可能是错的,不介意在这个问题上得到纠正)。
对于您在此处描述的问题类型,我个人通常会执行以下操作,基本上是将整个事情委托给多线程Cython/C++。这需要一些工作,但并非不可能,而且我不确定目前是否真的有可行的替代方案。
以下是构建基块:
首先,您的
df.x.values
、df.y.values
只是 numpy 数组。 This link 展示了如何从此类数组中获取 C 指针。现在您有了指针,您可以使用 Cython 的
prange
编写一个真正的多线程程序并从这一点开始放弃任何 Python(您现在处于 C++ 领域) .所以假设你有 k 线程扫描你的 6GB 数组,并且线程 i 处理其键具有散列的组 i模k.对于 C 程序(这就是您的代码现在真正的样子),GNU 科学图书馆有一个 nice histogram module.
当
prange
完成后,您需要将 C++ 结构转换回 numpy 数组,然后再从那里转换回 DataFrame。在 Cython 中包装整个东西,并像普通的 Python 函数一样使用它。