二.Pandas数据分析

(一).Series学习

1.基本创建方法

# Pandas是Python中最常用的数据分析库,它提供了高效地处理和分析数据结构的函数和方法。
# Pandas的主要数据结构是Series和DataFrame。
# Series是一维数组,它可以包含任何数据类型。
# DataFrame是二维表格型的数据结构,它包含多个Series,每个Series可以包含不同的数据类型。

#Series的创建----通过列表的形式创建Series。
import pandas as pd
s = pd.Series([2, 4, 6, 8, 10])
print(s)
print('\n')

# 自定义索引
s1 = pd.Series([2, 4, 6, 8, 10], index=['a', 'b', 'c', 'd', 'e'])
print(s1)
print('\n')

# 定义name
s3 = pd.Series([2, 4, 6, 8, 10], index=['a', 'b', 'c', 'd', 'e'], name='月份')# 定义name属性
print(s3)
0     2
1     4
2     6
3     8
4    10
dtype: int64


a     2
b     4
c     6
d     8
e    10
dtype: int64


a     2
b     4
c     6
d     8
e    10
Name: 月份, dtype: int64
# 通过字典的形式创建Series。
# 字典的键作为Series的索引,字典的值作为Series的值。
s4 = pd.Series({'a': 2, 'b': 4, 'c': 6, 'd': 8, 'e': 10})
print(s4)
print('\n')

s5 = pd.Series(s4,index=['a','c'])
print(s5)
print('\n')

prices = {'apple': 2, 'banana': 3, 'orange': 4}
s2 = pd.Series(prices)
print(s2)

a     2
b     4
c     6
d     8
e    10
dtype: int64


a    2
c    6
dtype: int64


apple     2
banana    3
orange    4
dtype: int64

2.Series的属性

# Series的属性主要有:
# 1. index:Series的索引对象
# 2. values:Series的值
# 3. dtype/dtypes:数据类型
# 4.shape:Series的形状
# 5.ndim:series的维度
# 6.size:series的元素个数
# 7. name:series的名称
# 8.loc[]:显示索引,按标签索引或切片
# 9.iloc[]:隐示索引,按位置索引或切片
# 10.at[]:按标签索引单个值
# 11.iat[]:按位置索引单个值
s6 = pd.Series([1,2,3,4,5],index=['a','b','c','d','e'],name='test')
print(s6)
print('\n')

print(s6.index)
print('\n')

print(s6.values)
print('\n')

print(s6.shape,s6.ndim,s6.size)
print('\n')

print(s6.dtype)
print('\n')

print(s6.name)
print('\n')

print(s6.loc['a'])#按标签索引--显示索引
print(s6.loc['a':'c'])#按标签索引--切片---包含左右端点
print('\n')

print(s6.iloc[1])#按位置索引--隐示索引
print(s6.iloc[0:3])#按位置索引--切片--包含左端点,不包含右端点
print('\n')

print(s6.at['a'])#按标签索引单个值
print('\n')

print(s6.iat[1])#按位置索引单个值

a    1
b    2
c    3
d    4
e    5
Name: test, dtype: int64


Index(['a', 'b', 'c', 'd', 'e'], dtype='object')


[1 2 3 4 5]


(5,) 1 5


int64


test


1
a    1
b    2
c    3
Name: test, dtype: int64


2
a    1
b    2
c    3
Name: test, dtype: int64


1


2

3.访问Series的数据

# 访问Series的数据有两种方式:
# 1.通过标签索引:通过索引值访问数据,返回单个值。
# 2.通过位置索引:通过位置索引访问数据,返回单个值。
s6 = pd.Series([1,2,3,4,5],index=['a','b','c','d','e'],name='test')

# 1.通过标签索引:通过索引值访问数据,返回单个值。
print(s6['a'])
# 2.通过位置索引:通过位置索引访问数据,返回单个值。--可以运行,但不推荐--位置和标签容易混淆
print(s6[0])
print('\n')

#bool索引
print(s6[s6>2])
print(s6[s6<3])
print('\n')

s7 = pd.Series([1,2,3,4,5,6,7,8,9,10],index=['a','b','c','d','e','f','g','h','i','j'],name='test6666')
print(s7.head())#默认查看前5行数据
print(s7.head(3))#查看前3行数据
print('\n')
print(s7.tail())#默认查看后5行数据
print(s7.tail(3))#查看后3行数据
1
1


c    3
d    4
e    5
Name: test, dtype: int64
a    1
b    2
Name: test, dtype: int64


a    1
b    2
c    3
d    4
e    5
Name: test6666, dtype: int64
a    1
b    2
c    3
Name: test6666, dtype: int64


f     6
g     7
h     8
i     9
j    10
Name: test6666, dtype: int64
h     8
i     9
j    10
Name: test6666, dtype: int64


C:\Users\haozh\AppData\Local\Temp\ipykernel_34464\2349729913.py:9: FutureWarning: Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]`
  print(s6[0])

4.Series的常用方法


# Series的常用方法有:
# 1.head():查看前几行数据
# 2.tail():查看后几行数据
# 3.isin():判断Series中是否包含某些值
# 4.isna():判断Series中是否有缺失值--NaN or None
# 5.sum():求和
# 6.mean():求均值
# 7.median():求中位数
# 8.std():求标准差
# 9.var():求方差
# 10.describe():查看Series的描述性统计信息---count, mean, std, min, max, median, 75%, 25%
# 11.mode():查看Series的众数
# 12quantile():计算分位数
# 13.nunique():计算Series的唯一值个数
# 14.unique():查看Series的唯一值
# 15.value_counts():查看Series中每个值出现的次数
# 16.count():计算Series的非空元素个数
# 17.drop_duplicates():删除Series中重复的值
# 18.sample():随机抽样
# 19.sort_values():排序
# 20.replace():替换值
# 21.keys():查看Series的索引
# 22.values():查看Series的值

import numpy as np
import pandas as pd
s8 = pd.Series([10,2,np.nan,None,3,4,5],index=['A','B','C','D','E','F','G'],name='常用用法')
print(s8)
print('\n')

print(s8.head())#默认查看前5行数据
print(s8.head(2))#查看前2行数据
print('\n')

print(s8.tail())#默认查看后5行数据
print(s8.tail(2))#查看后2行数据
print('\n')

# 查看所有的描述信息---s.describe()
# count:非空元素个数----不包括NaN and None
# mean:均值
# std:标准差
# min:最小值
# 25%:25%分位数
# 50%:中位数
# 75%:75%分位数
# max:最大值
print('描述信息为:')
print(s8.describe())
print('\n')

print('元素个数为:',s8.count())#计算Series的非空元素个数
print('索引方法1为:',s8.keys())#查看Series的索引----方法--有()
print('索引方法2为:',s8.index)#查看Series的索引----属性--无()
print('值为:',s8.values)
print('\n')

print('判断是否为缺失值nan:')
print(s8.isna())#判断Series中是否有缺失值--NaN or None
print('\n')

print('判断Series中是否包含某些值:')
print(s8.isin([4,5,6]))#检查每个元素是否在参数集合中
print('\n')

print('排序:')
print(s8.sort_values())#排序
print('\n')

print('求和:',s8.sum())
print('求均值:',s8.mean())
print('求中位数:',s8.median())
print('求标准差:',s8.std())
print('求方差:',s8.var())
print('最小值:',s8.min())
print('最大值:',s8.max())
print('0.25分位数:',s8.quantile(0.25))
print('0.75分位数:',s8.quantile(0.75))
print('\n')
# 现在列表中每个数只出现了一次,所以不存在众数。
s8['H'] = 4#增加一个元素--4出现了两次--众数为4
print('众数:',s8.mode())
print('\n')
print(s8.value_counts())#查看Series中每个值出现的次数
print('\n')

print('删除Series中重复的值:')# 去重
print(s8.drop_duplicates())#删除Series中重复的值--返回Series
print(s8.unique())#查看Series的唯一值----返回列表
print(s8.nunique())#去重后,计算Series的唯一值个数
print('\n')

# 排序  值---索引
print('两种排序方式:')
print(s8.sort_index())#排序--按索引排序
print(s8.sort_values())#排序--按值排序

A    10.0
B     2.0
C     NaN
D     NaN
E     3.0
F     4.0
G     5.0
Name: 常用用法, dtype: float64


A    10.0
B     2.0
C     NaN
D     NaN
E     3.0
Name: 常用用法, dtype: float64
A    10.0
B     2.0
Name: 常用用法, dtype: float64


C    NaN
D    NaN
E    3.0
F    4.0
G    5.0
Name: 常用用法, dtype: float64
F    4.0
G    5.0
Name: 常用用法, dtype: float64


描述信息为:
count     5.000000
mean      4.800000
std       3.114482
min       2.000000
25%       3.000000
50%       4.000000
75%       5.000000
max      10.000000
Name: 常用用法, dtype: float64


元素个数为: 5
索引方法1为: Index(['A', 'B', 'C', 'D', 'E', 'F', 'G'], dtype='object')
索引方法2为: Index(['A', 'B', 'C', 'D', 'E', 'F', 'G'], dtype='object')
值为: [10.  2. nan nan  3.  4.  5.]


判断是否为缺失值nan:
A    False
B    False
C     True
D     True
E    False
F    False
G    False
Name: 常用用法, dtype: bool


判断Series中是否包含某些值:
A    False
B    False
C    False
D    False
E    False
F     True
G     True
Name: 常用用法, dtype: bool


排序:
B     2.0
E     3.0
F     4.0
G     5.0
A    10.0
C     NaN
D     NaN
Name: 常用用法, dtype: float64


求和: 24.0
求均值: 4.8
求中位数: 4.0
求标准差: 3.1144823004794877
求方差: 9.700000000000001
最小值: 2.0
最大值: 10.0
0.25分位数: 3.0
0.75分位数: 5.0


众数: 0    4.0
Name: 常用用法, dtype: float64


常用用法
4.0     2
10.0    1
2.0     1
3.0     1
5.0     1
Name: count, dtype: int64


删除Series中重复的值:
A    10.0
B     2.0
C     NaN
E     3.0
F     4.0
G     5.0
Name: 常用用法, dtype: float64
[10.  2. nan  3.  4.  5.]
5


两种排序方式:
A    10.0
B     2.0
C     NaN
D     NaN
E     3.0
F     4.0
G     5.0
H     4.0
Name: 常用用法, dtype: float64
B     2.0
E     3.0
F     4.0
H     4.0
G     5.0
A    10.0
C     NaN
D     NaN
Name: 常用用法, dtype: float64

(二).Series的案例

# 1.案例1:创建一个包含10名学生数学成绩的Series,成绩范围在50-100之间。
# 计算平均分、最高分、最低分、并找出高于平均分的学生人数.
import numpy as np
import pandas as pd
np.random.seed(42)#设置随机种子
score_arr = np.random.randint(50,101,size=10)#随机生成10名学生数学成绩
print(score_arr)
score_Series =pd.Series(score_arr,index=['学生'+str(i) for i in range(1,11)],name='数学成绩Series')
print(score_Series)
print('\n')

print('最高分为:',score_Series.max())
print('最低分为:',score_Series.min())
print('平均分为:',score_Series.mean())
print(score_Series>score_Series.mean())#高于平均分的学生--bool索引---true1 or false0
print(score_Series[score_Series>score_Series.mean()])#高于平均分的学生--Series

# 三种思路
print('高于平均分的学生人数为:',len(score_Series[score_Series>score_Series.mean()]))
print('高于平均分的学生人数为:',score_Series[score_Series>score_Series.mean()].count())
print('高于平均分的学生人数为:',sum(score_Series>score_Series.mean()))

[88 78 64 92 57 70 88 68 72 60]
学生1     88
学生2     78
学生3     64
学生4     92
学生5     57
学生6     70
学生7     88
学生8     68
学生9     72
学生10    60
Name: 数学成绩Series, dtype: int32


最高分为: 92
最低分为: 57
平均分为: 73.7
学生1      True
学生2      True
学生3     False
学生4      True
学生5     False
学生6     False
学生7      True
学生8     False
学生9     False
学生10    False
Name: 数学成绩Series, dtype: bool
学生1    88
学生2    78
学生4    92
学生7    88
Name: 数学成绩Series, dtype: int32
高于平均分的学生人数为: 4
高于平均分的学生人数为: 4
高于平均分的学生人数为: 4
#:2.案例2:---温度数据分析
# 给定某城市一周每天的最高温度Series,完成以下任务:
# 找出温度超过30度的天数
# 计算平均温度
# 将温度从高到低排序
# 找出温度变化最大的两天

import numpy as np
import pandas as pd
temperatures = pd.Series([28,31,29,32,30,27,33],index=['周一','周二','周三','周四','周五','周六','周日'],name='一周温度记录')
print('温度>30度的Series: ')
print(temperatures[temperatures>30])
print('温度大于30度的天数为:',len(temperatures[temperatures>30]))
print('平均温度为:',temperatures.mean())
print('\n')
print(temperatures.sort_values(ascending=False))#降序排序
print(temperatures.sort_values(ascending=True))#升序排序
print('\n')

#找出温度变化最大的两天
#28 31 29 32 30 27 33
#none 3 -2 3 -2 -3 6--温度变化
#temperatures.diff()#计算一阶差分
t3 = temperatures.diff().abs()#计算绝对值
print(t3)
print('\n')

print(t3.sort_values(ascending=False))
print('\n')
print('温度变化最大的两天为:',t3.sort_values(ascending=False).keys()[0:2].tolist())

温度>30度的Series: 
周二    31
周四    32
周日    33
Name: 一周温度记录, dtype: int64
温度大于30度的天数为: 3
平均温度为: 30.0


周日    33
周四    32
周二    31
周五    30
周三    29
周一    28
周六    27
Name: 一周温度记录, dtype: int64
周六    27
周一    28
周三    29
周五    30
周二    31
周四    32
周日    33
Name: 一周温度记录, dtype: int64


周一    NaN
周二    3.0
周三    2.0
周四    3.0
周五    2.0
周六    3.0
周日    6.0
Name: 一周温度记录, dtype: float64


周日    6.0
周二    3.0
周六    3.0
周四    3.0
周三    2.0
周五    2.0
周一    NaN
Name: 一周温度记录, dtype: float64


温度变化最大的两天为: ['周日', '周二']
# 3.案例3:---股票价格分析
# ---给定某股票连续10个交易日的收盘价Series:
# ---计算每日收益率(当日收盘价/昨日收盘价-1)
# ---找出收益率最高和最低的日期
# ---计算波动率(收益率的标准差)

import numpy as np
import pandas as pd
arr = [102.3,103.5,105.1,104.8,106.2,107.0,106.5,108.1,109.3,110.2]
index1 = pd.date_range('2023-01-01',periods=10)#生成日期索引---pd.date_range()----start,end,periods
price = pd.Series(arr,index1,name='股票价格')
print(price)
print('\n')

#计算每日收益率
#pct_change()方法----计算百分比变化---(当日/昨日-1)
print('每日收益率为:')
price_ret = price.pct_change()#计算百分比变化
print(price_ret)
print('\n')

print('收益率最大的值为:',price_ret.max())
print('收益率最小的值为:',price_ret.min())
#idxmax()方法----返回最大值对应的索引
#idxmin()方法----返回最小值对应的索引
print('收益率最高的日期为:',price_ret.idxmax())
print('收益率最低的日期为:',price_ret.idxmin())

#计算波动率
print('\n')
print('波动率为:',price_ret.std())
2023-01-01    102.3
2023-01-02    103.5
2023-01-03    105.1
2023-01-04    104.8
2023-01-05    106.2
2023-01-06    107.0
2023-01-07    106.5
2023-01-08    108.1
2023-01-09    109.3
2023-01-10    110.2
Freq: D, Name: 股票价格, dtype: float64


每日收益率为:
2023-01-01         NaN
2023-01-02    0.011730
2023-01-03    0.015459
2023-01-04   -0.002854
2023-01-05    0.013359
2023-01-06    0.007533
2023-01-07   -0.004673
2023-01-08    0.015023
2023-01-09    0.011101
2023-01-10    0.008234
Freq: D, Name: 股票价格, dtype: float64


收益率最大的值为: 0.015458937198067568
收益率最小的值为: -0.004672897196261627
收益率最高的日期为: 2023-01-03 00:00:00
收益率最低的日期为: 2023-01-07 00:00:00


波动率为: 0.007373623845361105
# 4.案例4:---销售数据分析
# ---某产品过去12个月的销售量Series:
# ---计算季度平均销售量(3个月为一季度)
# ---找出销售量最高的月份
# ---计算月度环比增长率---环比增长率=当月销量/上月销量-1    同比增长率=当月销量/去年同月销量-1
# ---找出连续增长超过两个月的月份

import numpy as np
import pandas as pd
arr_sales = [120,135,145,160,155,170,180,175,190,200,210,220]
index2 = pd.date_range('2022-01-01',periods=12,freq='MS')#生成月份索引---pd.date_range()----start,end,periods,freq='M'
#freq='MS'----表示月度频率;freq='QS'----表示季度频率;freq='AS'----表示年度频率
sales = pd.Series(arr_sales,index2,name='销售量')
print(sales)
print('\n')

#计算季度平均销售量
print('季度平均销售量为:')
sales_quarter = sales.resample('QS').mean()#resample()方法----重新采样---'Q'表示季度频率
print(sales_quarter)
print('\n')

#找出销售量最高的月份
print('销售量最高的月份为:',sales.idxmax())
print('\n')

#计算月度环比增长率
print('月度环比增长率为:')
sales_month_ret = sales.pct_change()#计算月度百分比变化
print(sales_month_ret)
print('\n')

# 找出连续增长超过两个月的月份
sales_month_ret_bool =sales_month_ret > 0
print(sales_month_ret_bool)
print(sales_month_ret_bool.rolling(window=3).sum())#rolling()方法----滚动窗口---window=3表示窗口大小为3
print('\n')
print(sales_month_ret_bool.rolling(window=3).sum()==3)
print('\n')
print(sales_month_ret_bool[sales_month_ret_bool.rolling(window=3).sum()==3].keys().tolist())

2022-01-01    120
2022-02-01    135
2022-03-01    145
2022-04-01    160
2022-05-01    155
2022-06-01    170
2022-07-01    180
2022-08-01    175
2022-09-01    190
2022-10-01    200
2022-11-01    210
2022-12-01    220
Freq: MS, Name: 销售量, dtype: int64


季度平均销售量为:
2022-01-01    133.333333
2022-04-01    161.666667
2022-07-01    181.666667
2022-10-01    210.000000
Freq: QS-JAN, Name: 销售量, dtype: float64


销售量最高的月份为: 2022-12-01 00:00:00


月度环比增长率为:
2022-01-01         NaN
2022-02-01    0.125000
2022-03-01    0.074074
2022-04-01    0.103448
2022-05-01   -0.031250
2022-06-01    0.096774
2022-07-01    0.058824
2022-08-01   -0.027778
2022-09-01    0.085714
2022-10-01    0.052632
2022-11-01    0.050000
2022-12-01    0.047619
Freq: MS, Name: 销售量, dtype: float64


2022-01-01    False
2022-02-01     True
2022-03-01     True
2022-04-01     True
2022-05-01    False
2022-06-01     True
2022-07-01     True
2022-08-01    False
2022-09-01     True
2022-10-01     True
2022-11-01     True
2022-12-01     True
Freq: MS, Name: 销售量, dtype: bool
2022-01-01    NaN
2022-02-01    NaN
2022-03-01    2.0
2022-04-01    3.0
2022-05-01    2.0
2022-06-01    2.0
2022-07-01    2.0
2022-08-01    2.0
2022-09-01    2.0
2022-10-01    2.0
2022-11-01    3.0
2022-12-01    3.0
Freq: MS, Name: 销售量, dtype: float64


2022-01-01    False
2022-02-01    False
2022-03-01    False
2022-04-01     True
2022-05-01    False
2022-06-01    False
2022-07-01    False
2022-08-01    False
2022-09-01    False
2022-10-01    False
2022-11-01     True
2022-12-01     True
Freq: MS, Name: 销售量, dtype: bool


[Timestamp('2022-04-01 00:00:00'), Timestamp('2022-11-01 00:00:00'), Timestamp('2022-12-01 00:00:00')]
# 5.案例5:---每小时销售数据分析
# ---某商店每小时销售额Series:
# ---按天重采样计算每日总销售额
# ---计算营业时间(8:00-22:00)和非营业时间的销售额比例
# ---找出销售额最高的三个小时

import numpy as np
import pandas as pd
np.random.seed(42)
hourly_sales = pd.Series(np.random.randint(0,100,size=24),index=pd.date_range('2025-01-01',periods=24,freq='h'))
print(hourly_sales)
print('\n')

#按天重采样计算每日总销售额
#resample()方法----重新采样---'D'表示日频率---'h'表示小时频率---'T'表示分钟频率---'S'表示秒钟频率
print('按天重采样计算每日总销售额:')
#hourly_sales.sum()
daily_sales = hourly_sales.resample('D').sum()
print(daily_sales)
print('\n')

# 计算营业时间(8:00-22:00)和非营业时间的销售额比例
# 方法1:between_time()方法----返回指定时间区间内的数据
working_sales = hourly_sales.between_time('8:00','22:00')#返回指定时间区间内的数据


#drop()方法----删除指定索引的数据
'''
nonworking_sales = hourly_sales.drop(working_sales.index)
print('\n')
print(working_sales)
print('\n')
'''


noworking_sales = hourly_sales[(hourly_sales.index.hour<8) | (hourly_sales.index.hour>22)]
print('\n')
print(working_sales)
print('\n')
print(noworking_sales)
print('\n')
print('工作时间的总销售额为:',working_sales.sum())
print('非工作时间的总销售额为:',noworking_sales.sum())
print('营业时间(8:00-22:00)和非营业时间的销售额比例:',working_sales.sum()/hourly_sales.sum())
print('\n')

#找出销售额最高的三个小时
print(hourly_sales.nlargest(3))
print('销售额最高的三个小时为:',hourly_sales.nlargest(3).index.tolist())#nlargest()方法----返回指定个数的最大值


2025-01-01 00:00:00    51
2025-01-01 01:00:00    92
2025-01-01 02:00:00    14
2025-01-01 03:00:00    71
2025-01-01 04:00:00    60
2025-01-01 05:00:00    20
2025-01-01 06:00:00    82
2025-01-01 07:00:00    86
2025-01-01 08:00:00    74
2025-01-01 09:00:00    74
2025-01-01 10:00:00    87
2025-01-01 11:00:00    99
2025-01-01 12:00:00    23
2025-01-01 13:00:00     2
2025-01-01 14:00:00    21
2025-01-01 15:00:00    52
2025-01-01 16:00:00     1
2025-01-01 17:00:00    87
2025-01-01 18:00:00    29
2025-01-01 19:00:00    37
2025-01-01 20:00:00     1
2025-01-01 21:00:00    63
2025-01-01 22:00:00    59
2025-01-01 23:00:00    20
Freq: h, dtype: int32


按天重采样计算每日总销售额:
2025-01-01    1205
Freq: D, dtype: int32




2025-01-01 08:00:00    74
2025-01-01 09:00:00    74
2025-01-01 10:00:00    87
2025-01-01 11:00:00    99
2025-01-01 12:00:00    23
2025-01-01 13:00:00     2
2025-01-01 14:00:00    21
2025-01-01 15:00:00    52
2025-01-01 16:00:00     1
2025-01-01 17:00:00    87
2025-01-01 18:00:00    29
2025-01-01 19:00:00    37
2025-01-01 20:00:00     1
2025-01-01 21:00:00    63
2025-01-01 22:00:00    59
Freq: h, dtype: int32


2025-01-01 00:00:00    51
2025-01-01 01:00:00    92
2025-01-01 02:00:00    14
2025-01-01 03:00:00    71
2025-01-01 04:00:00    60
2025-01-01 05:00:00    20
2025-01-01 06:00:00    82
2025-01-01 07:00:00    86
2025-01-01 23:00:00    20
dtype: int32


工作时间的总销售额为: 709
非工作时间的总销售额为: 496
营业时间(8:00-22:00)和非营业时间的销售额比例: 0.5883817427385892


2025-01-01 11:00:00    99
2025-01-01 01:00:00    92
2025-01-01 10:00:00    87
dtype: int32
销售额最高的三个小时为: [Timestamp('2025-01-01 11:00:00'), Timestamp('2025-01-01 01:00:00'), Timestamp('2025-01-01 10:00:00')]
Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐