首页Python【Python数据分析】4...

【Python数据分析】48.数据聚合和分组操作——数据聚合


本系列文章配套代码获取有以下三种途径:

  • 可以在以下网站查看,该网站是使用JupyterLite搭建的web端Jupyter环境,因此无需在本地安装运行环境即可使用,首次运行浏览器需要下载一些配置文件(大约20M):

https://returu.github.io/Python_Data_Analysis/lab/index.html
链接:https://pan.baidu.com/s/1MYkeYeVAIRqbxezQECHwcA?pwd=mnsj 提取码:mnsj
  • 前往GitHub详情页面,单击 code 按钮,选择Download ZIP选项:
https://github.com/returu/Python_Data_Analysis

根据《Python for Data Analysis 3rd Edition》翻译整理

—————————————————–

1.数据聚合:

聚合()是指所有根据数组产生标量值的数据转换过程。包括之前使用到的meancountmin,  sum等。

下面是一些优化的groupby 方法:

函数名
说明
any, all 如果任何(一个或多个值)或所有非 NA 值都是“真实的”,则返回 True
count 非 NA 值的数量
cummin, cummax 非 NA 值的最小和最大累积
cumsum 非 NA 值的累积和
cumprod 非 NA 值的累积
first, last 第一个和最后一个非 NA 值
mean 非 NA 值的平均值
median 非 NA 值的算术中位数
min, max 非 NA 值的最小值和最大值
nth 检索将出现在位置 n 的值,数据按排序顺序排列
ohlc 为类似时间序列的数据计算四个“open-high-low-close”统计数据
prod 非 NA 值的乘积
quantile 计算样本分位数
rank 非 NA 值的序数排名
size 计算组大小,将结果作为Series返回
sum 非 NA 值的总和
std, var 样本标准差和方差
你可以使用自行定义的聚合方法,并再调用已经在分组对象上定义好的方法。
 1>>> rng = np.random.default_rng(12345)
2
3>>> df = pd.DataFrame({"key1" : ["a""a", None, "b""b""a", None],
4...                    "key2" : pd.Series([12121, None, 1], dtype="Int64"),
5...                    "data1" : np.round(rng.standard_normal(7) , 2),
6...                    "data2" : np.round(rng.standard_normal(7) , 2)})
7
8>>> df
9   key1  key2  data1  data2
100     a     1  -1.42   0.65
111     a     2   1.26   0.36
122  None     1  -0.87  -1.95
133     b     2  -0.26   2.35
144     b     1  -0.08   0.97
155     a  <NA>  -0.74  -0.76
166  None     1  -1.37   0.90
例如,Series的nsmallest 方法用于选择前n小的数据,虽然该方法并没有显式地为GroupBy对象实现,但它是Series的方法。在内部GroupBy对Series进行切片,为每一块调用 piece.nsmallest(n),然后将其组装到结果对象中。
1>>> grouped = df.groupby("key1")
2
3>>> grouped["data1"].nsmallest(2)
4key1
5a     0   -1.42
6      5   -0.74
7b     3   -0.26
8      4   -0.08
9Name: data1, dtype: float64
要使用自定义的聚合函数,需要将函数传递给aggregate方法或其短别名 agg

自定义聚合函数通常比上面表中的优化函数慢得多。这是因为在构建中间组数据块时有一些额外的开销(函数调用、数据重排)。

 1# 自定义函数,每列最大值-最小值
2>>def peak_to_peak(arr):
3...     return arr.max() - arr.min()
4
5
6>>> df.groupby("key1").agg(peak_to_peak)
7      key2  data1  data2
8key1
9a        1   2.68   1.41
10b        1   0.18   1.38

另外,某些方法(如 describe)也是有效的,尽管严格来说它们不是聚合函数。

1>>> df.groupby("key1").describe()
2      key2                                            ... data2
3     count mean       std  min   25%  50%   75%  max  ... count      mean       std   min    25%   50%    75%   max
4key1                                                  ...
5a      2.0  1.5  0.707107  1.0  1.25  1.5  1.75  2.0  ...   3.0  0.083333  0.744603 -0.76 -0.200  0.36  0.505  0.65
6b      2.0  1.5  0.707107  1.0  1.25  1.5  1.75  2.0  ...   2.0  1.660000  0.975807  0.97  1.315  1.66  2.005  2.35
7
8[2 rows x 24 columns]

2.逐列或多函数应用:

如上所述,对一个Series 或 DataFrame 的所有列进行聚合,就是使用aggregate(或 agg)和所需函数,或调用 meanstd 等方法。

但是,你可能希望根据列使用不同的函数或同时使用多个函数进行聚合。

对于上述表 中的描述性统计信息,可以将函数名称作为字符串传递。

 1>>> df = pd.DataFrame({"key1" : ["a""a",  "b""b""a""b"],
2...                    "key2" : pd.Series(["x""y",  "y""x""x""y"]),
3...                    "data1" : [123456],
4...                    "data2" : [789101112]})
5
6>>> df
7  key1 key2  data1  data2
80    a    x      1      7
91    a    y      2      8
102    b    y      3      9
113    b    x      4     10
124    a    x      5     11
135    b    y      6     12
14
15>>> df.groupby(["key1","key2"])["data1"].agg("mean")
16key1  key2
17a     x       3.0
18      y       2.0
19b     x       4.0
20      y       4.5
21Name: data1, dtype: float64

如果改为传递函数或函数名称的列表,则会返回一个 DataFrame,其中列名取自函数名。传递的这些函数会各自运用于数据分组。

1>>> df.groupby(["key1","key2"])["data1"].agg(["mean","std",peak_to_peak])
2           mean       std  peak_to_peak
3key1 key2
4a    x      3.0  2.828427             4
5     y      2.0       NaN             0
6b    x      4.0       NaN             0
7     y      4.5  2.121320             3

你可以不接受 GroupBy 对象给予各列的名称;值得注意的是,lambda 函数的名称为“<lambda>”,这使得它们很难识别(可以通过函数的 name 属性查看)。因此,如果你传递一个(name, function)元组的列表,每个元组的第一个元素将用作 DataFrame 列名称(你可以将 二 元元组列表视为一种有序映射)。

1>>> df.groupby(["key1","key2"])["data1"].agg([("average", "mean"), ("stdev", np.std), ("Custom_Func", peak_to_peak)])
2           average     stdev  Custom_Func
3key1 key2
4a    x         3.0  2.828427            4
5     y         2.0       NaN            0
6b    x         4.0       NaN            0
7     y         4.5  2.121320            3

在 DataFrame 中有更多选择,可以指定一个函数列表以应用于所有列。

 1>>> functions = ["count""mean""max"]
2>>> df.groupby(["key1","key2"]).agg(functions)
3          data1          data2
4          count mean max count  mean max
5key1 key2
6a    x        2  3.0   5     2   9.0  11
7     y        1  2.0   2     1   8.0   8
8b    x        1  4.0   4     1  10.0  10
9     y        2  4.5   6     2  10.5  12
10
11# 也可以传递具有自定义名称的元组列表
12>>> ftuples = [("Average""mean"), ("Custom_Func", peak_to_peak)]
13>>> df.groupby(["key1","key2"]).agg(ftuples)
14            data1               data2
15          Average Custom_Func Average Custom_Func
16key1 key2
17a    x        3.0           4     9.0           4
18     y        2.0           0     8.0           0
19b    x        4.0           0    10.0           0
20     y        4.5           3    10.5           3
如果想要对一列或多列应用不同的函数。为此需要将含有列名与函数对应关系的字典传递给aggregate(或 agg)。

只有当多个函数应用于至少一列时,DataFrame 才会具有分层列。

 1>>> df.groupby(["key1","key2"]).agg({"data1" : np.max, "data2" : "sum"})
2           data1  data2
3key1 key2
4a    x         5     18
5     y         2      8
6b    x         4     10
7     y         6     21
8
9
10>>> df.groupby(["key1","key2"]).agg({"data1" : ["min""max""mean""std"],"data2" : [("Average""mean"), ("Custom_Func", peak_to_peak)]})
11          data1                      data2
12            min max mean       std Average Custom_Func
13key1 key2
14a    x        1   5  3.0  2.828427     9.0           4
15     y        2   2  2.0       NaN     8.0           0
16b    x        4   4  4.0       NaN    10.0           0
17     y        3   6  4.5  2.121320    10.5           3
3.返回不含行索引的聚合数据:

上述示例中,聚合数据返回时都有一个索引,有时是分层的,由唯一的分组键组成。

由于这并不总是需要的,因此可以通过将 as_index=False 传递给 groupby 来禁用分组键作为索引的行为。
 1>>> df.groupby(["key1","key2"]).mean()
2           data1  data2
3key1 key2
4a    x       3.0    9.0
5     y       2.0    8.0
6b    x       4.0   10.0
7     y       4.5   10.5
8
9>>> df.groupby(["key1","key2"] , as_index=False).mean()
10  key1 key2  data1  data2
110    a    x    3.0    9.0
121    a    y    2.0    8.0
132    b    x    4.0   10.0
143    b    y    4.5   10.5


本篇文章来源于微信公众号: 码农设计师

RELATED ARTICLES

欢迎留下您的宝贵建议

Please enter your comment!
Please enter your name here

- Advertisment -

Most Popular

Recent Comments