在数据分析和处理中,经常需要按照月份对时间序列数据进行分组和聚合。今天以高管违规数据为例, 想根据这份数据绘制月度高管违规量趋势,需要按照月份对数据进行分组,可以使用resample或groupby。本文知识点

  1. resample实现
  2. groupby实现
  3. resample和groupby运算结果是什么数据类型



一、resample实现步骤

  1. 导入xlsx数据 (点击跳转获取数据)
  2. 使用set_index函数将’公告日期’列设置为索引,以便能够使用时间序列的功能。
  3. 使用resample函数并指定频率为’M'(表示按照月份)来对时间序列数据进行分组。使用了size函数获取每组的记录数
  4. 打印了分组结果df_resampled,其中每一行代表一个月份的总和。
import pandas as pd

df = pd.read_excel('上市公司高管违规-原始数据.xlsx')

df['公告日期'] = pd.to_datetime(df['公告日期'])
df.set_index('公告日期', inplace=True)
df.head()


# 将'date'列设置为索引
#df.set_index('公告日期', inplace=True)

# 按月份对时间序列数据进行分组
df_resampled = df.resample('M').size()
#df_resampled = df.resample('30D').size()

# 打印分组结果
print(df_resampled)

Run

    公告日期
    1997-01-31      1
    1997-02-28      0
    1997-03-31      0
    1997-04-30      0
    1997-05-31      0
                 ... 
    2022-08-31    453
    2022-09-30    479
    2022-10-31    216
    2022-11-30    525
    2022-12-31    343
    Freq: M, Length: 312, dtype: int64

import matplotlib.pyplot as plt
import matplotlib
import matplotlib_inline
matplotlib_inline.backend_inline.set_matplotlib_formats('png', 'svg')
import scienceplots
import platform
import numpy as np


plt.style.use(['science', 'no-latex', 'cjk-sc-font'])
system = platform.system()  # 获取操作系统类型

if system == 'Windows':
    font = {'family': 'SimHei'}
elif system == 'Darwin':
    font = {'family': 'Arial Unicode MS'}
else:
    font = {'family': 'sans-serif'}
matplotlib.rc('font', **font)  # 设置全局字体


plt.figure(figsize=(10, 5))
plt.xlabel('日期')
plt.ylabel('月度违规量')
plt.title('月度上市公司高管违规量(1997-2022)')
df_resampled.plot()



二、groupby实现步骤

  1. 导入xlsx数据
  2. 使用set_index函数将’公告日期’列设置为索引,以便能够使用时间序列的功能。
  3. 使用groupby函数并指定频率为’M'(表示按照月份)来对时间序列数据进行分组。使用了size函数获取每组的记录数
  4. 打印了分组结果df_resampled,其中每一行代表一个月份的总和。
import pandas as pd

df2 = pd.read_excel('上市公司高管违规-原始数据.xlsx')

df2['公告日期'] = pd.to_datetime(df2['公告日期'])

# 将'date'列设置为索引
df2.set_index('公告日期', inplace=True)

# 按月份对时间序列数据进行分组
df2_grouped = df2.groupby(pd.Grouper(freq='M')).size()

# 打印分组结果
print(df2_grouped)

Run

    公告日期
    1997-01-31      1
    1997-02-28      0
    1997-03-31      0
    1997-04-30      0
    1997-05-31      0
                 ... 
    2022-08-31    453
    2022-09-30    479
    2022-10-31    216
    2022-11-30    525
    2022-12-31    343
    Freq: M, Length: 312, dtype: int64

import matplotlib.pyplot as plt
import matplotlib
import matplotlib_inline
matplotlib_inline.backend_inline.set_matplotlib_formats('png', 'svg')
import scienceplots
import platform
import numpy as np


plt.style.use(['science', 'no-latex', 'cjk-sc-font'])
system = platform.system()  # 获取操作系统类型

if system == 'Windows':
    font = {'family': 'SimHei'}
elif system == 'Darwin':
    font = {'family': 'Arial Unicode MS'}
else:
    font = {'family': 'sans-serif'}
matplotlib.rc('font', **font)  # 设置全局字体


plt.figure(figsize=(10, 5))
plt.xlabel('日期')
plt.ylabel('月度违规量')
plt.title('月度上市公司高管违规量(1997-2022)')
df2_grouped.plot()



三、深入理解

df2.resample(‘M’)或df2.groupby(pd.Grouper(freq=‘M’)) 返回的结果是什么类型的数据,有什么特点。

df2.resample('M')

Run

    <pandas.core.resample.DatetimeIndexResampler object at 0x7fece05fb160>

df2.groupby(pd.Grouper(freq='M')) 

Run

    <pandas.core.groupby.generic.DataFrameGroupBy object at 0x7fed31571df0>

只要遇到 < object at 0x7fece05fb160>,不知道这内部是什么。可以使用for循环拆解这个黑盒子

for x in df2.resample('M'):
    print(type(x), len(x))

Run

<class 'tuple'> 2
<class 'tuple'> 2
<class 'tuple'> 2
<class 'tuple'> 2
<class 'tuple'> 2
<class 'tuple'> 2
......

for x in df2.groupby(pd.Grouper(freq='M')):
    print(type(x), len(x))

Run

<class 'tuple'> 2
<class 'tuple'> 2
<class 'tuple'> 2
<class 'tuple'> 2
<class 'tuple'> 2
<class 'tuple'> 2
......

经过检查发现df2.resample(‘M’)或df2.groupby(pd.Grouper(freq=‘M’)) 内部都是由tuple组成的,而每个tuple又由「日期」和对应的「dataframe」组成。

for x in df2.resample('M'):
    print(type(x[0]), type(x[1]))

Run

<class 'pandas._libs.tslibs.timestamps.Timestamp'> <class 'pandas.core.frame.DataFrame'>
<class 'pandas._libs.tslibs.timestamps.Timestamp'> <class 'pandas.core.frame.DataFrame'>
<class 'pandas._libs.tslibs.timestamps.Timestamp'> <class 'pandas.core.frame.DataFrame'>
<class 'pandas._libs.tslibs.timestamps.Timestamp'> <class 'pandas.core.frame.DataFrame'>
<class 'pandas._libs.tslibs.timestamps.Timestamp'> <class 'pandas.core.frame.DataFrame'>
<class 'pandas._libs.tslibs.timestamps.Timestamp'> <class 'pandas.core.frame.DataFrame'>
......



广而告之