在 Python 中对 pandas 中的数据框进行分箱 [重复]

Posted

技术标签:

【中文标题】在 Python 中对 pandas 中的数据框进行分箱 [重复]【英文标题】:binning a dataframe in pandas in Python [duplicate] 【发布时间】:2013-06-01 14:10:21 【问题描述】:

鉴于 pandas 中的以下数据框:

import numpy as np
df = pandas.DataFrame("a": np.random.random(100), "b": np.random.random(100), "id": np.arange(100))

其中id 是由ab 值组成的每个点的ID,我如何将ab 分箱到一组指定的箱中(这样我就可以将ab 在每个 bin 中的中值/平均值)?对于df 中的任何给定行,df 可能具有ab(或两者)的NaN 值。

这是一个使用 Joe Kington 的解决方案的更好的示例,它具有更真实的df。我不确定的是如何访问下面每个df.a 组的df.b 元素:

a = np.random.random(20)
df = pandas.DataFrame("a": a, "b": a + 10)
# bins for df.a
bins = np.linspace(0, 1, 10)
# bin df according to a
groups = df.groupby(np.digitize(df.a,bins))
# Get the mean of a in each group
print groups.mean()
## But how to get the mean of b for each group of a?
# ...

【问题讨论】:

【参考方案1】:

可能有更有效的方法(我觉得pandas.crosstab 在这里会很有用),但我会这样做:

import numpy as np
import pandas

df = pandas.DataFrame("a": np.random.random(100),
                       "b": np.random.random(100),
                       "id": np.arange(100))

# Bin the data frame by "a" with 10 bins...
bins = np.linspace(df.a.min(), df.a.max(), 10)
groups = df.groupby(np.digitize(df.a, bins))

# Get the mean of each bin:
print groups.mean() # Also could do "groups.aggregate(np.mean)"

# Similarly, the median:
print groups.median()

# Apply some arbitrary function to aggregate binned data
print groups.aggregate(lambda x: np.mean(x[x > 0.5]))

编辑:由于 OP 专门要求b 的方法被a 中的值分箱,所以就这样做

groups.mean().b

此外,如果您希望索引看起来更好(例如,将间隔显示为索引),就像在 @bdiamante 的示例中所做的那样,请使用 pandas.cut 而不是 numpy.digitize。 (向比达曼特致敬。我没有意识到pandas.cut 的存在。)

import numpy as np
import pandas

df = pandas.DataFrame("a": np.random.random(100), 
                       "b": np.random.random(100) + 10)

# Bin the data frame by "a" with 10 bins...
bins = np.linspace(df.a.min(), df.a.max(), 10)
groups = df.groupby(pandas.cut(df.a, bins))

# Get the mean of b, binned by the values in a
print groups.mean().b

这会导致:

a
(0.00186, 0.111]    10.421839
(0.111, 0.22]       10.427540
(0.22, 0.33]        10.538932
(0.33, 0.439]       10.445085
(0.439, 0.548]      10.313612
(0.548, 0.658]      10.319387
(0.658, 0.767]      10.367444
(0.767, 0.876]      10.469655
(0.876, 0.986]      10.571008
Name: b

【讨论】:

优秀优雅!正是我想要的。根本不需要对数据框进行排序。 如果您想根据组访问b 值怎么办? groups.mean() 为您提供了仅a 的方法,我相信。 @user248237dfsf - 不,它给出了ab 的平均值(或者更确切地说,它给出了b 的平均值,由a 中的值组合而成,这就是我以为你在问)。 groups.mean() 返回一个DataFrame,因此您可以通过groups.mean()["b"] 访问由a 分箱的b 的方法。【参考方案2】:

不是 100% 确定这是否是您正在寻找的,但我认为您正在寻找以下内容:

In [144]: df = DataFrame("a": np.random.random(100), "b": np.random.random(100), "id":   np.arange(100))

In [145]: bins = [0, .25, .5, .75, 1]

In [146]: a_bins = df.a.groupby(cut(df.a,bins))

In [147]: b_bins = df.b.groupby(cut(df.b,bins))

In [148]: a_bins.agg([mean,median])
Out[148]:
                 mean    median
a
(0, 0.25]    0.124173  0.114613
(0.25, 0.5]  0.367703  0.358866
(0.5, 0.75]  0.624251  0.626730
(0.75, 1]    0.875395  0.869843

In [149]: b_bins.agg([mean,median])
Out[149]:
                 mean    median
b
(0, 0.25]    0.147936  0.166900
(0.25, 0.5]  0.394918  0.386729
(0.5, 0.75]  0.636111  0.655247
(0.75, 1]    0.851227  0.838805

当然,我不知道你想到了什么垃圾箱,所以你必须根据你的情况换掉我的垃圾箱。

【讨论】:

不错!我假设 OP 想用“a”来组合“b”,但回想起来,你的答案可能就是他们想要的。我会留下我的,因为我们的答案略有不同。 或许值得一提的是pandas.Dataframe(..)a_bins.agg([numpy.mean,numpy.median])【参考方案3】:

Joe Kington 的回答非常有帮助,但是,我注意到它并没有对所有数据进行分类。它实际上用 a = a.min() 省略了行。总结 groups.size() 给出的是 99 而不是 100。

为保证所有数据都被分箱,只需将分箱数传递给 cut(),该函数将自动将第一个[最后一个]分箱填充 0.1%,以确保包含所有数据。

df = pandas.DataFrame("a": np.random.random(100), 
                    "b": np.random.random(100) + 10)

# Bin the data frame by "a" with 10 bins...
groups = df.groupby(pandas.cut(df.a, 10))

# Get the mean of b, binned by the values in a
print(groups.mean().b)

在这种情况下,将 groups.size() 相加得到 100。

我知道对于这个特定问题来说这是一个挑剔的点,但对于我试图解决的类似问题,获得正确答案至关重要。

【讨论】:

【参考方案4】:

如果你不必坚持pandas分组,你可以使用scipy.stats.binned_statistic

from scipy.stats import binned_statistic

means = binned_statistic(df.a, df.b, bins=np.linspace(min(df.a), max(df.a), 10))

【讨论】:

以上是关于在 Python 中对 pandas 中的数据框进行分箱 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

如何在 FOR 循环中对 Python Pandas 列表中的元素执行字符串更改

如何在 python pandas 循环中对数据帧执行操作

在 pandas / python 中对条件值进行分组和计数

在 Pandas 中对包含 Python `range` 或类似列表的列执行合并

如何在 pct_change 计算中对 pandas DataFrame 中的多列进行分组

在 pandas DataFrame 中的滚动窗口上对数据进行排名