下述列名依次代表学校、年级、姓名、性别、身高、体重、是否为转系生、体测场次、测试时间、1000米成绩,本节只需使用其中的前七列。
df = pd.read_csv('test_information.csv')
print(df.columns) # 获取列索引
---------
Index(['School', 'Grade', 'Name', 'Gender', 'Height', 'Weight', 'Transfer',
'Test_Number', 'Test_Date', 'Time_Record'],
dtype='object')
df = df[df.columns[:7]] # 获取前7列数据表
print(df)
---------
School Grade ... Weight Transfer
0 Nanchang University 大一 ... 72 N
1 Nanchang University 大二 ... 48 N
2 Jiangxi University of Finance and Economics 大一 ... 60 N
3 Jiangxi University of Finance and Economics 大二 ... 57 N
4 Jiangxi Normal University 大一 ... 57 N
5 Jiangxi Normal University 大二 ... 75 N
6 Nanchang Hangkong University 大一 ... 52 N
7 Nanchang Hangkong University 大二 ... 45 N
[8 rows x 7 columns]
head, tail 函数分别表示返回表或者序列的前 n 行和后 n 行,其中 n 默认为 5。
print(df.head()) # 输出表格的前5行
---------
School Grade ... Weight Transfer
0 Nanchang University 大一 ... 72 N
1 Nanchang University 大二 ... 48 N
2 Jiangxi University of Finance and Economics 大一 ... 60 N
3 Jiangxi University of Finance and Economics 大二 ... 57 N
4 Jiangxi Normal University 大一 ... 57 N
[5 rows x 7 columns]
print(df.tail()) # 输出表格的后5行
---------
School Grade ... Weight Transfer
3 Jiangxi University of Finance and Economics 大二 ... 57 N
4 Jiangxi Normal University 大一 ... 57 N
5 Jiangxi Normal University 大二 ... 75 N
6 Nanchang Hangkong University 大一 ... 52 N
7 Nanchang Hangkong University 大二 ... 45 N
[5 rows x 7 columns]
print(df.head(2)) # 输出表格的前2行
---------
School Grade Name Gender Height Weight Transfer
0 Nanchang University 大一 Li Lanqing Male 175.0 72 N
1 Nanchang University 大二 Cao Yu Female 168.3 48 N
print(df.tail(2)) # 输出表格的后2行
---------
School Grade Name ... Height Weight Transfer
6 Nanchang Hangkong University 大一 Wang Huijuan ... 170.0 52 N
7 Nanchang Hangkong University 大二 Shen Wenxuan ... 159.9 45 N
[2 rows x 7 columns]
info, describe 分别返回表的信息概况和表中数值列对应的主要统计量。
info, describe 只能实现较少信息的展示,如果想要对一份数据集进行全面且有效的观察,特别是在列较多的情况下,推荐使用 pandas-profiling 包。
print(df.info())
---------
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 8 entries, 0 to 7
Data columns (total 7 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 School 8 non-null object
1 Grade 8 non-null object
2 Name 8 non-null object
3 Gender 8 non-null object
4 Height 8 non-null float64
5 Weight 8 non-null int64
6 Transfer 8 non-null object
dtypes: float64(1), int64(1), object(5)
memory usage: 576.0+ bytes
None
print(df.describe())
---------
Height Weight
count 8.000000 8.00000
mean 169.850000 58.25000
std 6.989993 10.66034
min 159.900000 45.00000
25% 166.125000 51.00000
50% 169.150000 57.00000
75% 171.925000 63.00000
max 183.200000 75.00000
在 Series 和 DataFrame 上定义了许多统计函数,最常见的是 sum, mean, median, var, std, max, min 。用身高和体重列进行如下演示。
这些特征统计函数都有 axis 参数,当 axis=0 时表示按列统计,当 axis=1 时表示按行统计,默认 axis=0 。
df_demo = df[['Height', 'Weight']]
print(df_demo)
---------
Height Weight
0 175.0 72
1 168.3 48
2 170.9 60
3 165.0 57
4 166.5 57
5 183.2 75
6 170.0 52
7 159.9 45
# 逐行求和
print(df_demo.sum(axis=1))
---------
0 247.0
1 216.3
2 230.9
3 222.0
4 223.5
5 258.2
6 222.0
7 204.9
dtype: float64
# 逐列求和
print(df_demo.sum())
---------
Height 1358.8
Weight 466.0
dtype: float64
# 逐列求最大值
print(df_demo.max())
---------
Height 183.2
Weight 75.0
dtype: float64
# 逐列求最小值
print(df_demo.min())
---------
Height 159.9
Weight 45.0
dtype: float64
# 逐列求均值
print(df_demo.mean())
---------
Height 169.85
Weight 58.25
dtype: float64
# 逐列求方差
print(df_demo.var())
---------
Height 48.860000
Weight 113.642857
dtype: float64
# 逐列求标准差
print(df_demo.std())
---------
Height 6.989993
Weight 10.660340
dtype: float64
# 逐列求中位数
print(df_demo.median())
---------
Height 169.15
Weight 57.00
dtype: float64
# 逐列求分位数
print(df_demo.quantile(q=0.3)) # 默认q=0.5
---------
Height 166.68
Weight 52.50
Name: 0.3, dtype: float64
# 逐列求非缺失值个数
print(df_demo.count())
---------
Height 8
Weight 8
dtype: int64
# 逐列求最大值对应的索引
print(df_demo.idxmax())
---------
Height 5
Weight 5
dtype: int64
# 逐列求最小值对应的索引
print(df_demo.idxmin())
---------
Height 7
Weight 7
dtype: int64
上面这些所有的函数,由于操作后返回的是标量,所以又称为聚合函数。
对序列使用 unique 和 nunique 可以分别得到其唯一值组成的列表和唯一值的个数,value_counts 可以得到唯一值和其对应出现的频数。
df = pd.read_csv('test_information.csv')
print(df['School'].unique())
---------
['Nanchang University' 'Jiangxi University of Finance and Economics'
'Jiangxi Normal University' 'Nanchang Hangkong University']
print(df['School'].nunique())
---------
4
print(df['School'].value_counts())
---------
Jiangxi University of Finance and Economics 2
Nanchang Hangkong University 2
Jiangxi Normal University 2
Nanchang University 2
Name: School, dtype: int64
如果想要观察多个列组合的唯一值,可以使用 drop_duplicates 。其中的关键参数是 keep ,默认值 first 表示每个组合保留第一次出现的所在行,last 表示保留最后一次出现的所在行,False 表示把所有重复组合所在的行剔除。
df_demo = df[['School', 'Gender', 'Transfer']]
print(df_demo)
---------
School Gender Transfer
0 Nanchang University Male N
1 Nanchang University Female N
2 Jiangxi University of Finance and Economics Male N
3 Jiangxi University of Finance and Economics Male N
4 Jiangxi Normal University Male N
5 Jiangxi Normal University Male N
6 Nanchang Hangkong University Female N
7 Nanchang Hangkong University Female N
print(df_demo.drop_duplicates())
---------
School Gender Transfer
0 Nanchang University Male N
1 Nanchang University Female N
2 Jiangxi University of Finance and Economics Male N
4 Jiangxi Normal University Male N
6 Nanchang Hangkong University Female N
# 保留只出现过一次的学校、性别和转系生组合
print(df_demo.drop_duplicates(keep=False))
---------
School Gender Transfer
0 Nanchang University Male N
1 Nanchang University Female N
# 在Series上也可以使用
print(df['School'].drop_duplicates())
---------
0 Nanchang University
2 Jiangxi University of Finance and Economics
4 Jiangxi Normal University
6 Nanchang Hangkong University
Name: School, dtype: object
此外,duplicated 和 drop_duplicates 的功能类似,但前者返回是否重复的布尔列表,其 keep 参数与后者一致。其返回的序列,把重复元素设为 True ,否则为 False 。drop_duplicates 等价于把 duplicated 为 True 的对应行剔除。
# 默认keep='first',第一个重复的为False,后面的为True
print(df_demo.duplicated())
---------
0 False
1 False
2 False
3 True
4 False
5 True
6 False
7 True
dtype: bool
# 所有重复的布尔值都为True
print(df_demo.duplicated(keep=False))
---------
0 False
1 False
2 True
3 True
4 True
5 True
6 True
7 True
dtype: bool
# 在Series上也可以使用
print(df['School'].duplicated())
---------
0 False
1 True
2 False
3 True
4 False
5 True
6 False
7 True
Name: School, dtype: bool
一般而言,替换操作是针对某一个列进行的,因此下面的例子都以 Series 举例。pandas 中的替换函数可以归纳为三类:映射替换、逻辑替换、数值替换。此处介绍映射替换中的replace用法。
在 replace 中,可以通过字典构造,或者传入两个列表来进行替换。
print(df['Gender'])
---------
0 Male
1 Female
2 Male
3 Male
4 Male
5 Male
6 Female
7 Female
Name: Gender, dtype: object
print(df['Gender'].replace({'Male': 0, 'Female': 1}))
---------
0 0
1 1
2 0
3 0
4 0
5 0
6 1
7 1
Name: Gender, dtype: int64
print(df['Gender'].replace(['Male', 'Female'], [0, 1]))
---------
0 0
1 1
2 0
3 0
4 0
5 0
6 1
7 1
Name: Gender, dtype: int64
逻辑替换包括了 where 和 mask ,这两个函数是完全对称的:where 函数在传入条件为 False 的对应行进行替换,而 mask 在传入条件为 True 的对应行进行替换,当不指定替换值时,替换为缺失值。
需要注意的是,传入的条件只需是与被调用的 Series 索引一致的布尔序列即可。
s = pd.Series([-1, 1.2345, 199, -50])
print(s.where(s<0))
---------
0 -1.0
1 NaN
2 NaN
3 -50.0
dtype: float64
print(s.where(s<0, 100))
---------
0 -1.0
1 100.0
2 100.0
3 -50.0
dtype: float64
print(s.mask(s<0))
---------
0 NaN
1 1.2345
2 199.0000
3 NaN
dtype: float64
print(s.mask(s<0, -100))
---------
0 -100.0000
1 1.2345
2 199.0000
3 -100.0000
dtype: float64
数值替换包含了 round, abs, clip 方法,它们分别表示取几位小数、取绝对值和截断。
s = pd.Series([-1, 1.2345, 100, -50])
print(s.round(2))
---------
0 -1.00
1 1.23
2 199.00
3 -50.00
dtype: float64
print(s.abs())
---------
0 1.0000
1 1.2345
2 199.0000
3 50.0000
dtype: float64
# 两个数分别表示上下截断边界,小于0的数为0,大于2的数为2
print(s.clip(0, 2))
---------
0 0.0000
1 1.2345
2 2.0000
3 0.0000
dtype: float64
排序共有两种方式,其一为值排序,其二为索引排序,对应的函数是 sort_values 和 sort_index 。
df_demo = df[['Name', 'Grade', 'Height', 'Weight']]
print(df_demo)
---------
Name Grade Height Weight
0 Li Lanqing 大一 175.0 72
1 Cao Yu 大二 168.3 48
2 Wang Risheng 大一 170.9 60
3 Zhang Yi 大二 165.0 57
4 Xiong Zhihao 大一 166.5 57
5 Zhang Haiyan 大二 183.2 75
6 Wang Huijuan 大一 170.0 52
7 Shen Wenxuan 大二 159.9 45
# 根据Height列数值按升序排列所有行
print(df_demo.sort_values('Height'))
---------
Name Grade Height Weight
7 Shen Wenxuan 大二 159.9 45
3 Zhang Yi 大二 165.0 57
4 Xiong Zhihao 大一 166.5 57
1 Cao Yu 大二 168.3 48
6 Wang Huijuan 大一 170.0 52
2 Wang Risheng 大一 170.9 60
0 Li Lanqing 大一 175.0 72
5 Zhang Haiyan 大二 183.2 75
# 根据Height列数值按降序排列所有行
print(df_demo.sort_values('Height', ascending=False))
---------
Name Grade Height Weight
5 Zhang Haiyan 大二 183.2 75
0 Li Lanqing 大一 175.0 72
2 Wang Risheng 大一 170.9 60
6 Wang Huijuan 大一 170.0 52
1 Cao Yu 大二 168.3 48
4 Xiong Zhihao 大一 166.5 57
3 Zhang Yi 大二 165.0 57
7 Shen Wenxuan 大二 159.9 45
在排序中,经常遇到多列排序的问题,比如在体重相同的情况下,对身高进行排序,并且保持身高降序排列,体重升序排列。
# 先根据体重升序排列,在体重相同的情况下再根据身高降序排列
print(df_demo.sort_values(['Weight', 'Height'], ascending=[True, False]))
---------
Name Grade Height Weight
7 Shen Wenxuan 大二 159.9 45
1 Cao Yu 大二 168.3 48
6 Wang Huijuan 大一 170.0 52
4 Xiong Zhihao 大一 166.5 57
3 Zhang Yi 大二 165.0 57
2 Wang Risheng 大一 170.9 60
0 Li Lanqing 大一 175.0 72
5 Zhang Haiyan 大二 183.2 75
索引排序的用法和值排序完全一致,只不过元素的值在索引中,此时需要指定索引列的名字或者列号,用参数 level 表示。另外,需要注意的是字符串的排列顺序由字母顺序决定。
df_demo = df[['Name', 'Grade', 'Height', 'Weight']]
print(df_demo.sort_index(ascending=False)) # 按降序排列
---------
Name Grade Height Weight
7 Shen Wenxuan 大二 159.9 45
6 Wang Huijuan 大一 170.0 52
5 Zhang Haiyan 大二 183.2 75
4 Xiong Zhihao 大一 166.5 57
3 Zhang Yi 大二 165.0 57
2 Wang Risheng 大一 170.9 60
1 Cao Yu 大二 168.3 48
0 Li Lanqing 大一 175.0 72
df_demo = df_demo.set_index('Name') # 将Name列设置成索引列
print(df_demo)
---------
Grade Height Weight
Name
Li Lanqing 大一 175.0 72
Cao Yu 大二 168.3 48
Wang Risheng 大一 170.9 60
Zhang Yi 大二 165.0 57
Xiong Zhihao 大一 166.5 57
Zhang Haiyan 大二 183.2 75
Wang Huijuan 大一 170.0 52
Shen Wenxuan 大二 159.9 45
print(df_demo.sort_index(level='Name')) # 根据索引列排序
---------
Grade Height Weight
Name
Cao Yu 大二 168.3 48
Li Lanqing 大一 175.0 72
Shen Wenxuan 大二 159.9 45
Wang Huijuan 大一 170.0 52
Wang Risheng 大一 170.9 60
Xiong Zhihao 大一 166.5 57
Zhang Haiyan 大二 183.2 75
Zhang Yi 大二 165.0 57
apply 方法常用于 DataFrame 的行迭代或者列迭代,apply的参数往往是一个以序列为输入的函数。例如对于 .mean() ,使用 apply 可以如下地写出。
df_demo = df[['Height', 'Weight']]
def my_mean(x):
res = x.mean()
return res
print(df_demo.apply(my_mean)) # 将df_demo表中的序列逐个输入到my_mean函数中
---------
Height 169.85
Weight 58.25
dtype: float64
同样的,可以利用 lambda 表达式使得书写简洁,这里的 x 就指代被调用的 df_demo 表中逐个输入的序列。
print(df_demo.apply(lambda x: x.mean()))
---------
Height 169.85
Weight 58.25
dtype: float64
若指定 axis=1 ,那么每次传入函数的就是行元素组成的 Series ,其结果与之前的逐行均值结果一致。
print(df_demo.apply(lambda x: x.mean(), axis=1))
---------
0 123.50
1 108.15
2 115.45
3 111.00
4 111.75
5 129.10
6 111.00
7 102.45
dtype: float64
得益于传入自定义函数的处理,apply 的自由度很高,但这是以性能为代价的。一般而言,使用 pandas 的内置函数处理与使用 apply 来处理同一个任务,其速度会相差较多,因此只有在确实存在自定义需求的情境下才考虑使用 apply 。