学习笔记

pandas查看DataFrame基本信息、统计计算、位置计算、数据选择

1.数据信息

pandas载入一个数据集后,可以对数据表做一些初步的验证,比如行名、列名是否一致,数据量是否有缺失,各列的数据类型等,接下来这些操作不仅对DataFrame适用,也可以用在Series上。

查看样本

加载完的数据可能由于量太大,我们需要查看验证部分样本数据,pandas提供了3种常用的样式查看方法:

df.head() #返回前N行的数据,默认前5行
df.tail() #返回最后N行的数据,默认最后5行
df.sample() #随机返回一样数据,也可以指定条数

df.列标签可以返回数据表中索引列+指定的列

查看DataFrame基本信息

执行df.shape会返回一个元组,该元组的第一个元素代表行数,第二个元素代表列数(不包含行标签(索引)与列标签)

如果对Series使用.shape,那么这个元组中就只有一个值和一个英文逗号,类似(1,)

df.info可以返回所有数据的类型、索引情况、行列数、各字段数据类型、内存占用等,不适用于Series。

df.dtypes可以返回每一列的数据类型以及DataFrame整体的类型,Series对应的操作是dtype

df.axes会读取索引列与表头,并将这两组数据以及对应的数据类型组成一个列表返回,格式如下:

df.axes
”’
[RangeIndex(start=0, stop=100, step=1),
Index([‘name’, ‘team’, ‘Q1’, ‘Q2’, ‘Q3’, ‘Q4′], dtype=’object’)]
”’

Series的axes会返回列索引内容,格式如下:

s.axes

# [RangeIndex(start=0, stop=100, step=1)]

DataFrame其他信息获取方法:

# 索引对象

df.index

# RangeIndex(start=0, stop=100, step=1)

# 列索引,Series不支持

df.columns

# Index([‘name’, ‘team’, ‘Q1’, ‘Q2’, ‘Q3’, ‘Q4′], dtype=’object’)

df.values # array(<所有值的列表矩阵>)

df.ndim # 2 维度数

df.size # 600行×列的总数,就是总共有多少数据

# 是否为空,注意,有空值不认为是空

df.empty # False

# Series的索引,DataFrame的列名

df.keys()

Series独有的方法:

s.name # ‘Q1’
s.array # 值组成的数组
s.dtype # 类型,dtype(‘int64’)
s.hasnans # False

s.name可获取索引的名称,需要区分的是上例数据中df.name也能正常执行,它其实是df调用数据字段的方法,因为正好有名为name的列,如果没有就会报错,DataFrame是没有此属性的。

2.统计计算

pandas可以对Series与DataFrame进行快速的描述性统计,如求和、平均数、最大值、方差等,这些是最基础也最实用的统计方法。

对于DataFrame,这些统计方法会按列进行计算,然后返回一个以列标签为索引,亿计算值为值的Series。

描述统计

df.describe()可以返回一个有多行的所有数字列的统计表DataFrame,每一行对应一个统计指标,有总数、平均数、标准差、最小值、四分位数、最大值等。

也就是计算原DataFrame每一列的总数、平均数、标准差、最小值、四分位数、最大值,然后将结果返回一个新的DataFrame。

如果没有数字,则会输出与字符串相关的统计数据,如数量、不重复值数、最大值(字符按首字母顺序)等。

df.describe()也支持对时间数据的描述性统计:

(pd.Series(pd.date_range('2000-01-01', '2000-05-01'))
 .describe(datetime_is_numeric=True)
)
'''
count                    122
mean     2000-03-01 12:00:00
min      2000-01-01 00:00:00
25%      2000-01-31 06:00:00
50%      2000-03-01 12:00:00
75%      2000-03-31 18:00:00
max      2000-05-01 00:00:00
dtype: object
'''

还可以自己指定分位数(一般情况下,默认值包含中位数),指定和排除数据类型:

df.describe(percentiles=[.05, .25, .75, .95])
df.describe(include=[np.object, np.number]) # 指定类型
df.describe(exclude =[np.object]) # 排除类型

数学统计

在未来版本可能会报错

pandas支持常用的数学统计方法,如平均数mean()、中位数、众数、方差等,还可以结合NumPy使用更加丰富的统计功能。

对DataFrame使用统计函数后,会返回一个Series,原DataFrame的列标签会变成索引,每个索引对应它的计算结果,会忽略掉DataFrame非数值类型的列,如果DataFrame没有任何数字类型列,则会报错

对Series使用统计函数,只会返回一个数字,也就是计算结果。

默认情况下,统计函数是按列统计的,如果要按行来统计,可以传入axis参数,列传index或0,行传columns或1

df.mean(axis='columns')
df.mean(axis=1) # 效果同上
df.mean(1) # 效果同上
'''
0     49.50
1     41.75
2     54.75
3     84.50
4     65.25
      ...
95    67.00
96    31.25
97    53.00
98    58.50
99    44.75
Length: 100, dtype: float64
'''

上述代码值对数字类型的列起作用,会忽略文本等其他类型,此外可以发现,索引依然是从0开始的序列索引,让人无法分辨,所以需要先用set_index()函数指定某一列为索引,然后再计算。

pandas中统计函数如下:

df.mean() # 返回所有列的均值
df.mean(1) # 返回所有行的均值,下同
df.corr() # 返回列与列之间的相关系数
df.count() # 返回每一列中的非空值的个数
df.max() # 返回每一列的最大值
df.min() # 返回每一列的最小值
df.abs() # 绝对值
df.median() # 返回每一列的中位数
df.std() # 返回每一列的标准差,贝塞尔校正的样本标准偏差
df.var() # 无偏方差
df.sem() # 平均值的标准误差
df.mode() # 众数
df.prod() # 连乘
df.mad() # 平均绝对偏差
df.cumprod() # 累积连乘,累乘
df.cumsum(axis=0) # 累积连加,累加
df.nunique() # 去重数量,不同值的量
df.idxmax() # 每列最大值的索引名
df.idxmin() # 每列最小值的索引名
df.cummax() # 累积最大值
df.cummin() # 累积最小值
df.skew() # 样本偏度(第三阶)
df.kurt() # 样本峰度(第四阶)
df.quantile() # 样本分位数(不同 % 的值)

pandas还提供了一些特殊的用法

# 很多支持指定行列(默认是axis=0列)等参数
df.mean(1) # 按行计算
# 很多函数均支持
df.sum(0, skipna=False) # 不除缺失数据
# 很多函数均支持
df.sum(level='blooded') # 索引级别
df.sum(level=0)
# 执行加法操作所需的最小有效值数
df.sum(min_count=1)

非统计计算

除了简单的数学统计外,我们往往还需要对数据做非统计性计算,如去重、格式化等。方法有下面这些:

df.all() # 该列数值是否全都可以表示为True

df.any() #该列数值是否至少有一个可以表示为True

# 四舍五入

df.round(2) # 指定字段指定保留小数位,如有

df.round({‘Q1’: 2, ‘Q2’: 0})

df.round(-1) # 保留10位

# 每个列的去重值的数量

df.nunique() #不算重复的,每一列有多少个值

s.nunique() # 本列的去重值

# 真假检测

df.isna() # 值的真假值替换

df.notna() # 与上相反

以下可以传给一个值或者另一个DataFrame,对数据进行广播方式计算,返回计算后的DataFrame:

df + 1 # 等运算

df.add() # 加

df.sub() # 减

df.mul() # 乘

df.div() # 除

df.mod() # 模,除后的余数

df.pow() # 指数幂

df.dot(df2) # 矩阵运算

以下是Series专有的一些函数:

# 不重复的值及数量

s.value_counts()

s.value_counts(normalize=True) # 重复值的频率

s.value_counts(sort=False) # 不按频率排序

s.unique() # 去重的值 array

s.is_unique # 是否有重复

# 最大最小值

s.nlargest() # 最大的前5个

s.nlargest(15) # 最大的前15个

s.nsmallest() # 最小的前5个

s.nsmallest(15) # 最小的前15个

s.pct_change() # 计算与前一行的变化百分比

s.pct_change(periods=2) # 前两行

s1.cov(s2) # 两个序列的协方差

3.位置计算

diff()和shift()经常被用来计算数据的增量变化,rank()用来生成数据的整体排名。

位置差值diff()

df.diff()可以做位移差操作,经常用来计算一个序列数据中上一个数据和下一个数据之间的差值,如增量研究。

每一行默认返回这一行减上一行的计算结果,可以填写参数来指定计算的位置,1就是这一行减上一行,-1就是这一行减下一行,以此类推。

默认被减的数列下移一位,原数据在同位置上对移动后的数据相减,得到一个新的序列,第一位由于被减数下移,没有数据,所以结果为NaN。

可以传入一个数值来规定移动多少位,负数代表移动方向相反。

非数字的Series类型使用此方法会报错,DataFrame会对所有数字列移动计算,同时不允许有非数字类型。

DataFrame可以新增一列来存放计算结果:数据表[‘新列’]=数据表.列标签.diff())

DataFrame除了可以纵向计算,还可以横向计算,但需要选择需要计算的数据范围,比如:

df.loc[:5,’列标签1′:’列标签2′].diff(axis=1) #loc选择数据范围,:5表示前5行,然后另一个参数指定从哪个列标签到哪个列标签,最后在.diff()中加入axis=1参数表示横向计算,会返回一个DataFrame。

位置移动

shift()可以对数据位移但不进行任何计算,支持上下左右移动,移动后目标位置的类型无法接收的为NaN。

不填参数默认整体下移一行,最上一行有空缺,字符串类型会被填充None,数值类型的列会被填充NaN.

可以指定某一列上下移动,返回一个Series:df.列标签.shift(-1)”

如果设置axis=1,那么就会横向移动,整体右移一位

# 整体下移一行,最顶的一行为NaN
df.shift()
df.shift(3) # 移三行
# 整体上移一行,最底的一行为NaN
df.Q1.head().shift(-1)
# 向右移动一位
df.shift(axis=1)
df.shift(3, axis=1) # 移三位
# 向左移动一位
df.shift(-1, axis=1)
# 实现了df.Q1.diff()
df.Q1 - df.Q1.shift()

位置序号

rank()可以生成数据的排序值替换原来的数据值,它支持对所有类型数据进行排序,如英文会按字母排序。使用rank()的典型例子有学生的成绩表,给出排名。

如果这一列的内容是字符串,那么按照英文字母,最前面的英文字母排第一,如果是数字类型,数值最小的排第一

如果为rank()方法加入axis=1的参数,可以横向,也就是在在一行中排序,会忽略掉非数字形式的列,在未来这一功能可能会被移除

如果为rank()方法加入pct=True参数,可以将序数转换成从0到1的小数,数值最小,或者首字母排名最靠前,在排序结果中分配的小数的值也就越小

method参数可以设置,在排序过程中出现相同值的处理方法,可取的值有下面几个:

average:序号的平均值,如并列第1名,则按二次元计算(1+2)/2,都显示1.5,下个数据的值为3。

min:最小的序数,如并列第1名,则都显示1,下个数据为3。

max:最大的序数,如并列第1名,则都显示1,下个数据为2。

first:如并列第1名,则都显示1,下个数据为2。dense:按照索引的先后显示。

如果遇到空值,可以传入na_option=’bottom’,把空值放在最后,值为top放在最前。

4.数据选择

通过loc与iloc方法,可以模拟Excel对数据的选择查询操作,可以选择一列、一行,甚至按条件筛选数据。

pandas中常用的数据选择操作:

操作语法
选择列df[col]
按索引选择行df.loc[label]
按数字索引选择行df.iloc[label]
使用切片选择行df[起始值:最终值]
用表达式筛选行df[bool_vec]

选择列

选择DataFrame的列可以有以下几种格式:

df.列标签 #返回Series

需要注意的是,这样的方法只有在列标签可以作为一个合法的Python变量才能使用,如果列标签以数字开头,或者有空格,则会报错,如果想用这种方法,需要先将特定的列标签进行处理,比如将空格替换成下划线,或者增加前缀

df[‘列标签’] #返回Series 只能选择一列,选择多列需要2个中括号

df[[‘列标签1′,’列标签2’]] #选择多列,注意有2个中括号,返回的类型为DataFrame

切片方式选择行

可以像列表那样利用切片功能选择部分行的数据,但是不支持仅索引一条数据:

需要注意的是,切片时,索引值从0开始,并且不会保留最后一个额索引的值,比如[0:2],智慧保留索引值为0、1的元素,不包含索引值2的元素

df[:2] # 前两行数据
df[4:10]	#索引值4到索引值9的行
df[:] # 所有数据,一般不这么用
df[:10:2] # 按步长取
s[::-1] # 反转顺序
df[2] # 报错!

轴标签loc

可以根据索引或列的名称来选择

df.loc的格式是df.loc[<行表达式>,<列表达式>],如列表达式部分不传,则返回所有列,

Series仅支持行表达式进行索引的部分。

loc操作通过索引和列的条件筛选出数据,如果仅返回一条数据,则类型为Series。

返回结果如果是Series,原DataFrame数据表的列标签会变成索引,原数据表列标签下的每个值,会变成每一行索引对应的值,类似于进行了行与列互换的操作:

df.loc[0] #选择索引值为0的行

可以先将一列指定为索引,然后根据这新的索引,也就是原来列标签的内容来选择行

df.set_index(‘列标签’).loc[‘列标签下的内容’]

如果选择多行,可以在loc参数中加入英文冒号,表示从哪一行到哪一行

df.loc[0:10] #从索引值为0的行到索引值为10的行

仅在索引值为从0开始的自然数序列有用,如果自己设置了其它索引,那么df.loc参数就不是数字,而是加了引号的文本:df.loc[‘起始行’:’结束行’]

df.loc[:]表示选择所有行

如果loc后面跟着两个中括号,也就是df.loc[[]],也可以选择多行,

比如df.loc[[0,3,1]]就是输出索引值分别为0,3,1的行,行的排序也会跟loc参数中一致

附带列筛选,必须先有行筛选。列部分的表达式可以是一个由希望筛选的表明组成的列表,也可以是一个用冒号隔开的切片形式,来表示从左到右全部包含,左侧和右侧可以分别省略,表示本侧所有列。

df.loc[0:3,[‘列标签1′,’列标签2’]] #选择索引值从0到3的行,然后只取列标签1和列标签2的列

df.loc[ : , ‘列标签’ : ] #表示选择所有行,然后筛选从列标签1开始的往后所有的列

总之,选择列标签时,如果按照切片的方式,列标签的表达式为英文冒号,如果按照自己指定的行,则是中括号[]里填写自己指定的列标签。

按数字索引.iloc

与loc[]可以使用索引和列的名称不同,利用iloc[<行表达式>,<列表达式>]格式可以使用数字索引(行和列的0~n索引)进行数据筛选,意味着iloc[]的两个表达式仅支持数字切片形式,其他方面都是相同的。

注意切片操作时,-1表示倒数第二

df.iloc[:3] # 前三行

s.iloc[:3] # 序列中的前三个

df.iloc[:] # 所有数据

df.iloc[2:20:3] # 步长为3

df.iloc[:3, [0,1]] # 前两列

df.iloc[:3, :] # 所有列

df.iloc[:3, :-2] # 从右往左第三列以左的所有列

以上方法可以在行和列的表达式中混用,.iloc中的表达式部分支持条件表达式,可以按条件数据查询。

取具体指.at/.iat

如果需要取数据中一个具体的值,就像取平面直角坐标系中的一个点一样,可以使用.at[]来实现。

.at类似于loc,仅取一个具体的值,结构为df.at[<索引>,<列名>]。

如果是Series,可以直接通过索引取到对应的值

格式:

df.at[‘索引’,’列标签’] #如果DataFrame的索引不是数字序列,而是文本,需要加入引号

也可以先锁定列,再锁定值:df.列标签.[索引]

# 注:索引是字符,需要加引号
df.at[4, 'Q1'] # 65
df.set_index('name').at['Ben', 'Q1'] # 21 索引是name
df.at[0, 'name'] # 'Liver'
df.loc[0].at['name'] # 'Liver'
# 指定列的值对应其他列的值
df.set_index('name').at['Eorge', 'team'] # 'C'
df.set_index('name').team.at['Eorge'] # 'C'
# 指定列的对应索引的值
df.team.at[3] # 'C'

iat和iloc一样,仅支持数字索引

df.iat[行索引值, 列索引值] #通过行索引与列索引取值,这里的索引与DataFrame的index无关

df.loc[index].iat[1] # 先根据DataFrame的索引index选择行,然后根据普通的数字索引选择列,索引值0表示第一列

数据获取.get

.get可以做类似字典的操作,如果没有值,则返回默认值。

使用方法是df.get(‘列标签’,’默认返回值’),如果找到列标签,返回列标签的 那一列,,如果没找到指定的列标签,返回设定好的返回值,不填写则默认返回None。

如果是DataFrame,key需要传入列名,返回的是此列的Series,

如果是Series,需要传入索引,返回的是一个定值。

数据截取.truncate

df.druncate()可以对DataFrame和Series进行截取,可以将索引传入before和after参数,将这个区间以外的数据剔除。

意思就是,只取第几行到到几行的内容,给定2个行的数字索引值即可。

测试的过程中,发现值对默认的从0开始的数字序列索引有效,如果将索引改成其他列,则会报错。

df.truncate(2,5) #从索引值为2的行到索引值为5的行

索引选择器

pd.IndexSlice是一个专门的索引选择器,它的使用方法类似df.loc[]切片中的方法,常用在多层索引中,以及需要指定应用范围(subset参数)的函数中,特别是在链式方法中。

df.loc[pd.IndexSlice[:, ['Q1', 'Q2']]]
# 变量化使用
idx = pd.IndexSlice
df.loc[idx[:, ['Q1', 'Q2']]]
df.loc[idx[:, 'Q1':'Q4'], :] # 多索引

还可以按条件查询创建复杂的选择器,一下是几个案例:

# 创建复杂条件选择器
selected = df.loc[(df.列标签1=='A') & (df.列标签2>90)]
idxs = pd.IndexSlice[selected.index, '列标签']
# 应用选择器
df.loc[idxs]
# 选择这部分区域加样式
df.style.applymap(style_fun, subset=idxs)

发表回复