数据科学必备Pandas数据分组GroupBy方法汇总

学Python数据科学,玩游戏、学日语、搞编程一条龙。

整套学习自学教程中应用的数据都是《三國志》、《真·三國無雙》系列游戏中的内容。

分解和可视化的方式 复习和巩固 Pandas GroupBy。无论是刚开始使用 Pandas 并想掌握其核心功能,还是希望填补对 .groupby() 的理解都是对未来工作有帮助的。

在这里插入图片描述

数据准备

  1. 三国志13的人物数据。
  2. 空气质量数据集 包含定期气体传感器读数。
  3. 新闻数据集 其中包含数十万条新闻文章的元数据。

示例1:三国志人物数据

目标通过剖析国会历史成员的数据。

import pandas as pd

df = pd.read_excel("Romance of the Three Kingdoms 13/人物详情数据.xlsx",)
df.head()

在这里插入图片描述

GroupBy 聚合操作

问题1(单列聚合):想看看所有人物中的分类情况,即文臣、武将。应该如何操作?

SQL 操作。

SELECT `分類`, count(`名前`) as `数量`
FROM df
GROUP BY `分類`
ORDER BY `分類`;

Pandas 操作。

n_by_state = df.groupby("分類")["名前"].count().nlargest(2) 
n_by_state

分類
武官    520
文官    336
Name: 名前, dtype: int64

问题2(多列聚合):如何按照性别和分类进行人物的区分?
SQL 操作。

SELECT `分類`,`性別` count(`名前`) as `数量`
FROM df
GROUP BY `分類`,`性別`
ORDER BY `分類`,`性別`;

Pandas 操作。

n_by_state = df.groupby(["分類", "性別"])["名前"].count()
n_by_state

分類  性別
文官  女      35301
武官  女      11509
?   男       1
Name: 名前, dtype: int64

GroupBy 的工作原理

.groupby() 其实是split-apply-combine 这么三步的过程:将表拆分为组、对每个较小的表应用一些操作、合并结果

split 拆分过程

Pandas GroupBy 对象并查看拆分的一种有用方法是对其进行迭代。

by_state = df.groupby("分類")

# 查看每次聚合的元素对应的前两条数据
for state, frame in by_state:
    print(f"前 2 条数据 {
      
      state!r}")
    print("------------------------")
    print(frame.head(2), end="\n\n")

在这里插入图片描述
.groups 属性将提供一 { ‘group name’ : ‘group label’ } 的字典,by_state 是一个dict 类型的数据,因此可以实用 key 选择的方式进行访问。

list(by_state["寿命"])

[('文官', 1       70
  2       65
  3       67
  4       60
  5       57
        ... 
  845    107
  848    102
  850    104
  852    100
  855     99
  Name: 寿命, Length: 336, dtype: int64), ('武官', 0       36
  6       63
  7       55
  8       72
  11      56
        ... 
  847    103
  851    107
  853     99
  854     99
  856     99
  Name: 寿命, Length: 520, dtype: int64), ('?', 849    104
  Name: 寿命, dtype: int64)]

可以实用 .get_group() 获取相关的详细 value 信息。

by_state.get_group("文官")

在这里插入图片描述
apply 应用过程

将相同的操作(或可调用)应用于拆分阶段生成的每个 单元。

state, frame = next(iter(by_state))  
state
'文官'

frame.head(5)

在这里插入图片描述

combine 组合过程

frame["名前"].count()
336

示例2:空气质量数据集

import pandas as pd

df = pd.read_excel("数据科学必备Pandas实用操作GroupBy数据分组详解/AirQualityUCI.xlsx",parse_dates=[["Date","Time"]])
df.rename(columns={
    
    
    "CO(GT)": "co",
    "Date_Time": "tstamp",
    "T": "temp_c",
    "RH": "rel_hum",
    "AH": "abs_hum",
    },inplace = True
)

df.set_index("tstamp",inplace=True)

在这里插入图片描述

co 是该小时的平均一氧化碳读数,而 temp_c、rel_hum 和 abs_hum 分别是该小时的平均温度、相对湿度和绝对湿度。 观察从 2004 年 3 月持续到 2005 年 4 月。

df.index.min()
Timestamp('2004-03-10 18:00:00')

df.index.max()
Timestamp('2005-04-04 14:00:00')

派生数组进行分组

利用星期的数据(转化后的字符串)进行分组聚合。

day_names = df.index.day_name()
day_names[:10]

Index(['Wednesday', 'Wednesday', 'Wednesday', 'Wednesday', 'Wednesday',
       'Wednesday', 'Thursday', 'Thursday', 'Thursday', 'Thursday'],
      dtype='object', name='tstamp')

问题1:查找一周中某天的平均一氧化碳 ( co ) 的数据。

df.groupby(day_names)["co"].mean()

tstamp
Friday      -24.583259
Monday      -30.063820
Saturday    -27.126414
Sunday      -35.432292
Thursday    -35.806176
Tuesday     -41.773864
Wednesday   -44.917647
Name: co, dtype: float64

问题2:按照星期每个时间段进行数据聚合。

hr = df.index.hour
df.groupby([day_names, hr])["co"].mean().rename_axis(["dow", "hr"])

dow        hr
Friday     0    -30.517857
           1    -30.792857
           2    -31.158929
           3    -31.398214
           4    -92.416071
                   ...    
Wednesday  19   -28.662500
           20   -28.916071
           21   -29.710714
           22   -30.378571
           23   -30.516071
Name: co, Length: 168, dtype: float64

问题3:将温度划分离散区间进行分组聚合。

bins = pd.cut(df["temp_c"], bins=3, labels=("cool", "warm", "hot"))
df[["rel_hum", "abs_hum"]].groupby(bins).agg(["mean", "median"])

在这里插入图片描述
问题4:按照年度、季度聚合数据处理。

df.groupby([df.index.year, df.index.quarter])["co"].agg(["max", "min"]).rename_axis(["year", "quarter"])

在这里插入图片描述

示例3:新闻聚合器数据集

import datetime as dt
import pandas as pd

def parse_millisecond_timestamp(ts):
    """转换 UTC 日期时间 """
    return dt.datetime.fromtimestamp(ts / 1000, tz=dt.timezone.utc)

df = pd.read_csv(
    "数据科学必备Pandas实用操作GroupBy数据分组详解/newsCorpora.csv",
    sep="\t",
    header=None,
    index_col=0,
    names=["title", "url", "outlet", "category", "cluster", "host", "tstamp"],
    parse_dates=["tstamp"],
    date_parser=parse_millisecond_timestamp,
    dtype={
    
    
        "outlet": "category",
        "category": "category",
        "cluster": "category",
        "host": "category",
    },
)
df.head()

在这里插入图片描述
category 的类别分别是 b商业、t科技、e娱乐、m健康。

问题1:计算包含某关键字进行数据的类别的聚合统计,并进行排序。

df.groupby("outlet", sort=False)["title"].apply(
	lambda ser: ser.str.contains("Fed").sum()
).nlargest(10)

outlet
Reuters                         161
NASDAQ                          103
Businessweek                     93
Investing.com                    66
Wall Street Journal \(blog\)     61
MarketWatch                      56
Moneynews                        55
Bloomberg                        53
GlobalPost                       51
Economic Times                   44
Name: title, dtype: int64

提高 GroupBy 性能

.groupby() .apply() 这种模式可能不是最优的。 .apply() 是将有效地对每个组执行 Python 循环。 这每当使用 .apply() 时可以利用 .groupby() 不仅接受一个或多个列名,还接受许多类似数组的结构。提取包含关键字符的数据,生成的数据是一个 Series,然后进行聚合。

mentions_fed = df["title"].str.contains("Fed")

import numpy as np

mentions_fed.groupby(
   df["outlet"], sort=False
).sum().nlargest(10).astype(np.uintc)

outlet
Reuters                         161
NASDAQ                          103
Businessweek                     93
Investing.com                    66
Wall Street Journal \(blog\)     61
MarketWatch                      56
Moneynews                        55
Bloomberg                        53
GlobalPost                       51
Economic Times                   44
Name: title, dtype: uint32

判断数据是否有丢失。

df["outlet"].shape == mentions_fed.shape
True

最后看一下执行的时间对比,速度提高了很多。

# Version 1: 使用 `.apply()`
df.groupby("outlet", sort=False)["title"].apply(
    lambda ser: ser.str.contains("Fed").sum()
).nlargest(10)

# Version 2: 使用 vectorization
mentions_fed = df["title"].str.contains("Fed")
mentions_fed.groupby(
    df["outlet"], sort=False
).sum().nlargest(10).astype(np.uintc)

在这里插入图片描述

Pandas GroupBy 方法汇总

在这里插入图片描述

聚合方法(也称为归约方法)

将许多数据点『混合』成关于这些数据点的聚合统计信息。一个例子是取 10 个数字的总和、平均值或中位数,结果只是一个数字。

其中包括.agg()、.aggregate()、.all()、.any()、.apply()、.corr()、.corrwith()、.count()、.cov()、.cumcount()、.cummax()、.cummin()、.cumprod()、.cumsum()、.describe()、.idxmax()、.idxmin()、.mad()、.max()、.mean()、.median()、.min()、.nunique()、.prod()、.sem()、.size()、.skew()、.std()、.sum()、.var()。

过滤器方法

会返回原始 DataFrame 的子集。这通常意味着使用 .filter() 根据有关该组及其子表的一些比较统计数据来删除整个组。在此定义下包含许多从每个组中排除特定行的方法也是有意义的。

其中包括:.filter()、.first()、.head()、.last()、.nth()、.tail()、.take()。

转换方法

返回一个 DataFrame 其形状和索引与原始数据相同,但值不同。使用聚合和过滤方法,生成的 DataFrame 通常会比输入 DataFrame 的大小更小。转换并非如此,它会转换单个值本身但保留原始 DataFrame 的形状。

其中包括:.bfill()、.diff()、.ffill()、.fillna()、.pct_change()、.quantile()、.rank()、.shift()、.transform()、.tshift()。

元方法

不关注调用 .groupby() 的原始对象,而是更专注于提供高级信息,例如组的数量和这些组的索引。

其中包括:.iter()、.get_group()、.groups、.indices、.ndim、.ngroup()、.ngroups、.dtypes。

绘图方法

模仿 Pandas Series 或 DataFrame 的绘图 API,通常将输出分成多个子图。

其中包括:.hist()、.ohlc()、.boxplot().plot() 。

猜你喜欢

转载自blog.csdn.net/qq_20288327/article/details/124884920