Pandas提供疾速,灵便和富于表现力的数据结构,是弱小的数据分析Python库。
本文收录于机器学习前置教程系列。
一、Series和DataFrame
Pandas建设在NumPy之上,更多NumPy相干的知识点能够参考我之前写的文章前置机器学习(三):30分钟把握罕用NumPy用法。
Pandas特地适宜解决表格数据,如SQL表格、EXCEL表格。有序或无序的工夫序列。具备行和列标签的任意矩阵数据。
关上Jupyter Notebook,导入numpy和pandas开始咱们的教程:
import numpy as npimport pandas as pd
1. pandas.Series
Series是带有索引的一维ndarray数组。索引值可不惟一,但必须是可哈希的。
pd.Series([1, 3, 5, np.nan, 6, 8])
输入:
0 1.01 3.02 5.03 NaN4 6.05 8.0dtype: float64
咱们能够看到默认索引值为0、1、2、3、4、5这样的数字。增加index
属性,指定其为'c','a','i','yong','j','i'。
pd.Series([1, 3, 5, np.nan, 6, 8], index=['c','a','i','yong','j','i'])
输入如下,咱们能够看到index是可反复的。
c 1.0a 3.0i 5.0yong NaNj 6.0i 8.0dtype: float64
2. pandas.DataFrame
DataFrame是带有行和列的表格构造。能够了解为多个Series对象的字典构造。
pd.DataFrame(np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]), index=['i','ii','iii'], columns=['A', 'B', 'C'])
输入表格如下,其中index
对应它的行,columns
对应它的列。
A | B | C | |
---|---|---|---|
i | 1 | 2 | 3 |
ii | 4 | 5 | 6 |
iii | 7 | 8 | 9 |
二、Pandas常见用法
1. 拜访数据
筹备数据,随机生成6行4列的二维数组,行标签为从20210101到20210106的日期,列标签为A、B、C、D。
import numpy as npimport pandas as pdnp.random.seed(20201212)df = pd.DataFrame(np.random.randn(6, 4), index=pd.date_range('20210101', periods=6), columns=list('ABCD'))df
展现表格如下:
A | B | C | D | |
---|---|---|---|---|
2021-01-01 | 0.270961 | -0.405463 | 0.348373 | 0.828572 |
2021-01-02 | 0.696541 | 0.136352 | -1.64592 | -0.69841 |
2021-01-03 | 0.325415 | -0.602236 | -0.134508 | 1.28121 |
2021-01-04 | -0.33032 | -1.40384 | -0.93809 | 1.48804 |
2021-01-05 | 0.348708 | 1.27175 | 0.626011 | -0.253845 |
2021-01-06 | -0.816064 | 1.30197 | 0.656281 | -1.2718 |
1.1 head()和tail()
查看表格前几行:
df.head(2)
展现表格如下:
A | B | C | D | |
---|---|---|---|---|
2021-01-01 | 0.270961 | -0.405463 | 0.348373 | 0.828572 |
2021-01-02 | 0.696541 | 0.136352 | -1.64592 | -0.69841 |
查看表格后几行:
df.tail(3)
展现表格如下:
A | B | C | D | |
---|---|---|---|---|
2021-01-04 | -0.33032 | -1.40384 | -0.93809 | 1.48804 |
2021-01-05 | 0.348708 | 1.27175 | 0.626011 | -0.253845 |
2021-01-06 | -0.816064 | 1.30197 | 0.656281 | -1.2718 |
1.2 describe()
describe
办法用于生成DataFrame的描述统计信息。能够很不便的查看数据集的散布状况。留神,这里的统计散布不蕴含NaN
值。
df.describe()
展现如下:
A | B | C | D | |
---|---|---|---|---|
count | 6 | 6 | 6 | 6 |
mean | 0.0825402 | 0.0497552 | -0.181309 | 0.22896 |
std | 0.551412 | 1.07834 | 0.933155 | 1.13114 |
min | -0.816064 | -1.40384 | -1.64592 | -1.2718 |
25% | -0.18 | -0.553043 | -0.737194 | -0.587269 |
50% | 0.298188 | -0.134555 | 0.106933 | 0.287363 |
75% | 0.342885 | 0.987901 | 0.556601 | 1.16805 |
max | 0.696541 | 1.30197 | 0.656281 | 1.48804 |
咱们首先回顾一下咱们把握的数学公式。
平均数(mean):
$$\bar x = \frac{\sum_{i=1}^{n}{x_i}}{n}$$
方差(variance):
$$s^2 = \frac{\sum_{i=1}^{n}{(x_i -\bar x)^2}}{n}$$
标准差(std):
$$s = \sqrt{\frac{\sum_{i=1}^{n}{(x_i -\bar x)^2}}{n}}$$
咱们解释一下pandas的describe统计信息各属性的意义。咱们仅以 A
列为例。
count
示意计数。A列有6个数据不为空。mean
示意平均值。A列所有不为空的数据平均值为0.0825402。std
示意标准差。A列的标准差为0.551412。min
示意最小值。A列最小值为-0.816064。即,0%的数据比-0.816064小。25%
示意四分之一分位数。A列的四分之一分位数为-0.18。即,25%的数据比-0.18小。50%
示意二分之一分位数。A列的四分之一分位数为0.298188。即,50%的数据比0.298188小。75%
示意四分之三分位数。A列的四分之三分位数为0.342885。即,75%的数据比0.342885小。max
示意最大值。A列的最大值为0.696541。即,100%的数据比0.696541小。
1.3 T
T
个别示意Transpose
的缩写,即转置。行列转换。
df.T
展现表格如下:
2021-01-01 | 2021-01-02 | 2021-01-03 | 2021-01-04 | 2021-01-05 | 2021-01-06 | |
---|---|---|---|---|---|---|
A | 0.270961 | 0.696541 | 0.325415 | -0.33032 | 0.348708 | -0.816064 |
B | -0.405463 | 0.136352 | -0.602236 | -1.40384 | 1.27175 | 1.30197 |
C | 0.348373 | -1.64592 | -0.134508 | -0.93809 | 0.626011 | 0.656281 |
D | 0.828572 | -0.69841 | 1.28121 | 1.48804 | -0.253845 | -1.2718 |
1.4 sort_values()
指定某一列进行排序,如下代码依据C
列进行正序排序。
df.sort_values(by='C')
展现表格如下:
A | B | C | D | |
---|---|---|---|---|
2021-01-02 | 0.696541 | 0.136352 | -1.64592 | -0.69841 |
2021-01-04 | -0.33032 | -1.40384 | -0.93809 | 1.48804 |
2021-01-03 | 0.325415 | -0.602236 | -0.134508 | 1.28121 |
2021-01-01 | 0.270961 | -0.405463 | 0.348373 | 0.828572 |
2021-01-05 | 0.348708 | 1.27175 | 0.626011 | -0.253845 |
2021-01-06 | -0.816064 | 1.30197 | 0.656281 | -1.2718 |
1.5 nlargest()
抉择某列最大的n行数据。如:df.nlargest(2,'A')
示意,返回A列最大的2行数据。
df.nlargest(2,'A')
展现表格如下:
A | B | C | D | |
---|---|---|---|---|
2021-01-02 | 0.696541 | 0.136352 | -1.64592 | -0.69841 |
2021-01-05 | 0.348708 | 1.27175 | 0.626011 | -0.253845 |
1.6 sample()
sample
办法示意查看随机的样例数据。
df.sample(5)
示意返回随机5行数据。
df.sample(5)
参数frac
示意fraction,分数的意思。frac=0.01即返回1%的随机数据作为样例展现。
df.sample(frac=0.01)
2. 抉择数据
2.1 依据标签抉择
咱们输出df['A']
命令选取A列。
df['A']
输入A列数据,同时也是一个Series对象:
2021-01-01 0.2709612021-01-02 0.6965412021-01-03 0.3254152021-01-04 -0.3303202021-01-05 0.3487082021-01-06 -0.816064Name: A, dtype: float64
df[0:3]
该代码与df.head(3)
同理。但df[0:3]
是NumPy的数组抉择形式,这阐明了Pandas对于NumPy具备良好的反对。
df[0:3]
展现表格如下:
A | B | C | D | |
---|---|---|---|---|
2021-01-01 | 0.270961 | -0.405463 | 0.348373 | 0.828572 |
2021-01-02 | 0.696541 | 0.136352 | -1.64592 | -0.69841 |
2021-01-03 | 0.325415 | -0.602236 | -0.134508 | 1.28121 |
通过loc办法指定行列标签。
df.loc['2021-01-01':'2021-01-02', ['A', 'B']]
展现表格如下:
A | B | |
---|---|---|
2021-01-01 | 0.270961 | -0.405463 |
2021-01-02 | 0.696541 | 0.136352 |
2.2 依据地位抉择
iloc
与loc
不同。loc
指定具体的标签,而iloc
指定标签的索引地位。df.iloc[3:5, 0:3]
示意选取索引为3、4的行,索引为0、1、2的列。即,第4、5行,第1、2、3列。
留神,索引序号从0开始。冒号示意区间,左右两侧别离示意开始和完结。如3:5
示意左开右闭区间[3,5)
,即不蕴含5本身。
df.iloc[3:5, 0:3]
A | B | C | |
---|---|---|---|
2021-01-04 | -0.33032 | -1.40384 | -0.93809 |
2021-01-05 | 0.348708 | 1.27175 | 0.626011 |
df.iloc[:, 1:3]
B | C | |
---|---|---|
2021-01-01 | -0.405463 | 0.348373 |
2021-01-02 | 0.136352 | -1.64592 |
2021-01-03 | -0.602236 | -0.134508 |
2021-01-04 | -1.40384 | -0.93809 |
2021-01-05 | 1.27175 | 0.626011 |
2021-01-06 | 1.30197 | 0.656281 |
2.3 布尔索引
DataFrame可依据条件进行筛选,当条件判断True
时,返回。当条件判断为False
时,过滤掉。
咱们设置一个过滤器用来判断A列是否大于0。
filter = df['A'] > 0filter
输入后果如下,能够看到2021-01-04
和2021-01-06
的行为False。
2021-01-01 True2021-01-02 True2021-01-03 True2021-01-04 False2021-01-05 True2021-01-06 FalseName: A, dtype: bool
咱们通过过滤器查看数据集。
df[filter]# df[df['A'] > 0]
查看表格咱们能够发现,2021-01-04
和2021-01-06
的行被过滤掉了。
A | B | C | D | |
---|---|---|---|---|
2021-01-01 | 0.270961 | -0.405463 | 0.348373 | 0.828572 |
2021-01-02 | 0.696541 | 0.136352 | -1.64592 | -0.69841 |
2021-01-03 | 0.325415 | -0.602236 | -0.134508 | 1.28121 |
2021-01-05 | 0.348708 | 1.27175 | 0.626011 | -0.253845 |
3. 解决缺失值
筹备数据。
df2 = df.copy()df2.loc[:3, 'E'] = 1.0f_series = {'2021-01-02': 1.0,'2021-01-03': 2.0,'2021-01-04': 3.0,'2021-01-05': 4.0,'2021-01-06': 5.0}df2['F'] = pd.Series(f_series)df2
展现表格如下:
A | B | C | D | F | E | |
---|---|---|---|---|---|---|
2021-01-01 | 0.270961 | -0.405463 | 0.348373 | 0.828572 | nan | 1 |
2021-01-02 | 0.696541 | 0.136352 | -1.64592 | -0.69841 | 1 | 1 |
2021-01-03 | 0.325415 | -0.602236 | -0.134508 | 1.28121 | 2 | 1 |
2021-01-04 | -0.33032 | -1.40384 | -0.93809 | 1.48804 | 3 | nan |
2021-01-05 | 0.348708 | 1.27175 | 0.626011 | -0.253845 | 4 | nan |
2021-01-06 | -0.816064 | 1.30197 | 0.656281 | -1.2718 | 5 | nan |
3.1 dropna()
应用dropna办法清空NaN值。留神:dropa办法返回新的DataFrame,并不会扭转原有的DataFrame。
df2.dropna(how='any')
以上代码示意,当行数据有任意的数值为空时,删除。
A | B | C | D | F | E | |
---|---|---|---|---|---|---|
2021-01-02 | 0.696541 | 0.136352 | -1.64592 | -0.69841 | 1 | 1 |
2021-01-03 | 0.325415 | -0.602236 | -0.134508 | 1.28121 | 2 | 1 |
3.2 fillna()
应用filna命令填补NaN值。
df2.fillna(df2.mean())
以上代码示意,应用每一列的平均值来填补空缺。同样地,fillna并不会更新原有的DataFrame,如需更新原有DataFrame应用代码df2 = df2.fillna(df2.mean())
。
展现表格如下:
A | B | C | D | F | E | |
---|---|---|---|---|---|---|
2021-01-01 | 0.270961 | -0.405463 | 0.348373 | 0.828572 | 3 | 1 |
2021-01-02 | 0.696541 | 0.136352 | -1.64592 | -0.69841 | 1 | 1 |
2021-01-03 | 0.325415 | -0.602236 | -0.134508 | 1.28121 | 2 | 1 |
2021-01-04 | -0.33032 | -1.40384 | -0.93809 | 1.48804 | 3 | 1 |
2021-01-05 | 0.348708 | 1.27175 | 0.626011 | -0.253845 | 4 | 1 |
2021-01-06 | -0.816064 | 1.30197 | 0.656281 | -1.2718 | 5 | 1 |
4. 操作方法
4.1 agg()
agg是Aggregate的缩写,意为聚合。
罕用聚合办法如下:
- mean(): Compute mean of groups
- sum(): Compute sum of group values
- size(): Compute group sizes
- count(): Compute count of group
- std(): Standard deviation of groups
- var(): Compute variance of groups
- sem(): Standard error of the mean of groups
- describe(): Generates descriptive statistics
- first(): Compute first of group values
- last(): Compute last of group values
- nth() : Take nth value, or a subset if n is a list
- min(): Compute min of group values
- max(): Compute max of group values
df.mean()
返回各列平均值
A 0.082540B 0.049755C -0.181309D 0.228960dtype: float64
可通过加参数axis查看行平均值。
df.mean(axis=1)
输入:
2021-01-01 0.2606112021-01-02 -0.3778602021-01-03 0.2174702021-01-04 -0.2960532021-01-05 0.4981562021-01-06 -0.032404dtype: float64
如果咱们想查看某一列的多项聚合统计怎么办?
这时咱们能够调用agg办法:
df.agg(['std','mean'])['A']
返回结果显示标准差std和均值mean:
std 0.551412mean 0.082540Name: A, dtype: float64
对于不同的列利用不同的聚合函数:
df.agg({'A':['max','mean'],'B':['mean','std','var']})
返回后果如下:
A | B | |
---|---|---|
max | 0.696541 | nan |
mean | 0.0825402 | 0.0497552 |
std | nan | 1.07834 |
var | nan | 1.16281 |
4.2 apply()
apply()是对办法的调用。
如df.apply(np.sum)
示意每一列调用np.sum办法,返回每一列的数值和。
df.apply(np.sum)
输入后果为:
A 0.495241B 0.298531C -1.087857D 1.373762dtype: float64
apply办法反对lambda表达式。
df.apply(lambda n: n*2)
A | B | C | D | |
---|---|---|---|---|
2021-01-01 | 0.541923 | -0.810925 | 0.696747 | 1.65714 |
2021-01-02 | 1.39308 | 0.272704 | -3.29185 | -1.39682 |
2021-01-03 | 0.65083 | -1.20447 | -0.269016 | 2.56242 |
2021-01-04 | -0.66064 | -2.80768 | -1.87618 | 2.97607 |
2021-01-05 | 0.697417 | 2.5435 | 1.25202 | -0.50769 |
2021-01-06 | -1.63213 | 2.60393 | 1.31256 | -2.5436 |
4.3 value_counts()
value_counts办法查看各行、列的数值反复统计。
咱们从新生成一些整数数据,来保障有肯定的数据反复。
np.random.seed(101)df3 = pd.DataFrame(np.random.randint(0,9,size = (6,4)),columns=list('ABCD'))df3
A | B | C | D | |
---|---|---|---|---|
0 | 1 | 6 | 7 | 8 |
1 | 4 | 8 | 5 | 0 |
2 | 5 | 8 | 1 | 3 |
3 | 8 | 3 | 3 | 2 |
4 | 8 | 3 | 7 | 0 |
5 | 7 | 8 | 4 | 3 |
调用value_counts()办法。
df3['A'].value_counts()
查看输入咱们能够看到 A列的数字8有两个,其余数字的数量为1。
8 27 15 14 11 1Name: A, dtype: int64
4.4 str
Pandas内置字符串解决办法。
names = pd.Series(['andrew','bobo','claire','david','4'])names.str.upper()
通过以上代码咱们将Series中的字符串全副设置为大写。
0 ANDREW1 BOBO2 CLAIRE3 DAVID4 4dtype: object
首字母大写:
names.str.capitalize()
输入为:
0 Andrew1 Bobo2 Claire3 David4 4dtype: object
判断是否为数字:
names.str.isdigit()
输入为:
0 False1 False2 False3 False4 Truedtype: bool
字符串宰割:
tech_finance = ['GOOG,APPL,AMZN','JPM,BAC,GS']tickers = pd.Series(tech_finance)tickers.str.split(',').str[0:2]
以逗号宰割字符串,后果为:
0 [GOOG, APPL]1 [JPM, BAC]dtype: object
5. 合并
5.1 concat()
concat用来将数据集串联起来。咱们先筹备数据。
data_one = {'Col1': ['A0', 'A1', 'A2', 'A3'],'Col2': ['B0', 'B1', 'B2', 'B3']}data_two = {'Col1': ['C0', 'C1', 'C2', 'C3'], 'Col2': ['D0', 'D1', 'D2', 'D3']}one = pd.DataFrame(data_one)two = pd.DataFrame(data_two)
应用concat办法将两个数据集串联起来。
pt(pd.concat([one,two]))
失去表格:
Col1 | Col2 | |
---|---|---|
0 | A0 | B0 |
1 | A1 | B1 |
2 | A2 | B2 |
3 | A3 | B3 |
0 | C0 | D0 |
1 | C1 | D1 |
2 | C2 | D2 |
3 | C3 | D3 |
5.2 merge()
merge相当于SQL操作中的join办法,用于将两个数据集通过某种关系连接起来
registrations = pd.DataFrame({'reg_id':[1,2,3,4],'name':['Andrew','Bobo','Claire','David']})logins = pd.DataFrame({'log_id':[1,2,3,4],'name':['Xavier','Andrew','Yolanda','Bobo']})
咱们依据name
来连贯两个张表,连贯形式为outer
。
pd.merge(left=registrations, right=logins, how='outer',on='name')
返回后果为:
reg_id | name | log_id | |
---|---|---|---|
0 | 1 | Andrew | 2 |
1 | 2 | Bobo | 4 |
2 | 3 | Claire | nan |
3 | 4 | David | nan |
4 | nan | Xavier | 1 |
5 | nan | Yolanda | 3 |
咱们留神,how : {'left', 'right', 'outer', 'inner'} 有4种连贯形式。示意是否选取左右两侧表的nan值。如left示意保留左侧表中所有数据,当遇到右侧表数据为nan值时,不显示右侧的数据。
简略来说,把left表和right表看作两个汇合。
- left示意取左表全副汇合+两表交加
- right示意取右表全副汇合+两表交加
- outer示意取两表并集
- inner示意取两表交加
6. 分组GroupBy
Pandas中的分组性能十分相似于SQL语句SELECT Column1, Column2, mean(Column3), sum(Column4)FROM SomeTableGROUP BY Column1, Column2
。即便没有接触过SQL也没有关系,分组就相当于把表格数据依照某一列进行拆分、统计、合并的过程。
筹备数据。
np.random.seed(20201212)df = pd.DataFrame({'A': ['foo', 'bar', 'foo', 'bar', 'foo', 'bar', 'foo', 'foo'], 'B': ['one', 'one', 'two', 'three', 'two', 'two', 'one', 'three'], 'C': np.random.randn(8), 'D': np.random.randn(8)})df
能够看到,咱们的A列和B列有很多反复数据。这时咱们能够依据foo/bar或者one/two进行分组。
A | B | C | D | |
---|---|---|---|---|
0 | foo | one | 0.270961 | 0.325415 |
1 | bar | one | -0.405463 | -0.602236 |
2 | foo | two | 0.348373 | -0.134508 |
3 | bar | three | 0.828572 | 1.28121 |
4 | foo | two | 0.696541 | -0.33032 |
5 | bar | two | 0.136352 | -1.40384 |
6 | foo | one | -1.64592 | -0.93809 |
7 | foo | three | -0.69841 | 1.48804 |
6.1 单列分组
咱们利用groupby
办法将上方表格中的数据进行分组。
df.groupby('A')
执行上方代码能够看到,groupby办法返回的是一个类型为DataFrameGroupBy
的对象。咱们无奈间接查看,须要利用聚合函数。参考本文4.1节。
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x0000014C6742E248>
咱们利用聚合函数sum试试。
df.groupby('A').sum()
展现表格如下:
A | C | D |
---|---|---|
bar | 0.559461 | -0.724868 |
foo | -1.02846 | 0.410533 |
6.2 多列分组
groupby
办法反对将多个列作为参数传入。
df.groupby(['A', 'B']).sum()
分组后显示后果如下:
A | B | C | D |
---|---|---|---|
bar | one | -0.405463 | -0.602236 |
one | -0.405463 | -0.602236 | |
three | 0.828572 | 1.28121 | |
two | 0.136352 | -1.40384 | |
foo | one | -1.37496 | -0.612675 |
three | -0.69841 | 1.48804 | |
two | 1.04491 | -0.464828 |
6.3 利用多聚合办法
咱们利用agg()
,将聚合办法数组作为参数传入办法。下方代码依据A分类且只统计C
列的数值。
df.groupby('A')['C'].agg([np.sum, np.mean, np.std])
能够看到bar组与foo组各聚合函数的后果如下:
A | sum | mean | std |
---|---|---|---|
bar | 0.559461 | 0.186487 | 0.618543 |
foo | -1.02846 | -0.205692 | 0.957242 |
6.4 不同列进行不同聚合统计
下方代码对C、D列别离进行不同的聚合统计,对C列进行求和,对D列进行标准差统计。
df.groupby('A').agg({'C': 'sum', 'D': lambda x: np.std(x, ddof=1)})
输入如下:
A | C | D |
---|---|---|
bar | 0.559461 | 1.37837 |
foo | -1.02846 | 0.907422 |
6.5 更多
更多对于Pandas的goupby
办法请参考官网:https://pandas.pydata.org/pandas-docs/stable/user_guide/groupby.html
三、Pandas 进阶用法
1. reshape
reshape
示意重塑表格。对于简单表格,咱们须要将其转换成适宜咱们了解的样子,比方依据某些属性分组后进行独自统计。
1.1 stack() 和 unstack()
stack
办法将表格分为索引和数据两个局部。索引各列保留,数据重叠搁置。
筹备数据。
tuples = list(zip(*[['bar', 'bar', 'baz', 'baz','foo', 'foo', 'qux', 'qux'], ['one', 'two', 'one', 'two','one', 'two', 'one', 'two']]))index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second'])
依据上方代码,咱们创立了一个复合索引。
MultiIndex([('bar', 'one'), ('bar', 'two'), ('baz', 'one'), ('baz', 'two'), ('foo', 'one'), ('foo', 'two'), ('qux', 'one'), ('qux', 'two')], names=['first', 'second'])
咱们创立一个具备复合索引的DataFrame。
np.random.seed(20201212)df = pd.DataFrame(np.random.randn(8, 2), index=index, columns=['A', 'B'])df
输入如下:
A | B | C | D |
---|---|---|---|
bar | one | 0.270961 | -0.405463 |
two | 0.348373 | 0.828572 | |
baz | one | 0.696541 | 0.136352 |
two | -1.64592 | -0.69841 | |
foo | one | 0.325415 | -0.602236 |
two | -0.134508 | 1.28121 | |
qux | one | -0.33032 | -1.40384 |
two | -0.93809 | 1.48804 |
咱们执行stack
办法。
stacked = df.stack()stacked
输入重叠(压缩)后的表格如下。留神:你应用Jupyter Notebook/Lab进行的输入可能和如下后果不太一样。下方输入的各位为了不便在Markdown中显示有肯定的调整。
first second bar one A 0.942502bar one B 0.060742bar two A 1.340975bar two B -1.712152baz one A 1.899275baz one B 1.237799baz two A -1.589069baz two B 1.288342foo one A -0.326792foo one B 1.576351foo two A 1.526528foo two B 1.410695qux one A 0.420718qux one B -0.288002qux two A 0.361586qux two B 0.177352dtype: float64
咱们执行unstack将数据进行开展。
stacked.unstack()
输入原表格。
A | B | C | D |
---|---|---|---|
bar | one | 0.270961 | -0.405463 |
two | 0.348373 | 0.828572 | |
baz | one | 0.696541 | 0.136352 |
two | -1.64592 | -0.69841 | |
foo | one | 0.325415 | -0.602236 |
two | -0.134508 | 1.28121 | |
qux | one | -0.33032 | -1.40384 |
two | -0.93809 | 1.48804 |
咱们退出参数level
。
stacked.unstack(level=0)#stacked.unstack(level=1)
当level=0
时失去如下输入,大家能够试试level=1
时输入什么。
second | first | bar | baz | foo | qux |
---|---|---|---|---|---|
one | A | 0.942502 | 1.89927 | -0.326792 | 0.420718 |
one | B | 0.060742 | 1.2378 | 1.57635 | -0.288002 |
two | A | 1.34097 | -1.58907 | 1.52653 | 0.361586 |
two | B | -1.71215 | 1.28834 | 1.4107 | 0.177352 |
1.2 pivot_table()
pivot_table示意透视表,是一种对数据动静排布并且分类汇总的表格格局。
咱们生成无索引列的DataFrame。
np.random.seed(99)df = pd.DataFrame({'A': ['one', 'one', 'two', 'three'] * 3, 'B': ['A', 'B', 'C'] * 4, 'C': ['foo', 'foo', 'foo', 'bar', 'bar', 'bar'] * 2, 'D': np.random.randn(12), 'E': np.random.randn(12)})df
展现表格如下:
A | B | C | D | E | |
---|---|---|---|---|---|
0 | one | A | foo | -0.142359 | 0.0235001 |
1 | one | B | foo | 2.05722 | 0.456201 |
2 | two | C | foo | 0.283262 | 0.270493 |
3 | three | A | bar | 1.32981 | -1.43501 |
4 | one | B | bar | -0.154622 | 0.882817 |
5 | one | C | bar | -0.0690309 | -0.580082 |
6 | two | A | foo | 0.75518 | -0.501565 |
7 | three | B | foo | 0.825647 | 0.590953 |
8 | one | C | foo | -0.113069 | -0.731616 |
9 | one | A | bar | -2.36784 | 0.261755 |
10 | two | B | bar | -0.167049 | -0.855796 |
11 | three | C | bar | 0.685398 | -0.187526 |
通过观察数据,咱们能够显然得出A、B、C列的具备肯定属性含意。咱们执行pivot_table
办法。
pd.pivot_table(df, values=['D','E'], index=['A', 'B'], columns=['C'])
上方代码的意思为,将D、E列作为数据列,A、B作为复合行索引,C的数据值作为列索引。
('D', 'bar') | ('D', 'foo') | ('E', 'bar') | ('E', 'foo') | |
---|---|---|---|---|
('one', 'A') | -2.36784 | -0.142359 | 0.261755 | 0.0235001 |
('one', 'B') | -0.154622 | 2.05722 | 0.882817 | 0.456201 |
('one', 'C') | -0.0690309 | -0.113069 | -0.580082 | -0.731616 |
('three', 'A') | 1.32981 | nan | -1.43501 | nan |
('three', 'B') | nan | 0.825647 | nan | 0.590953 |
('three', 'C') | 0.685398 | nan | -0.187526 | nan |
('two', 'A') | nan | 0.75518 | nan | -0.501565 |
('two', 'B') | -0.167049 | nan | -0.855796 | nan |
('two', 'C') | nan | 0.283262 | nan | 0.270493 |
2. 工夫序列
date_range
是Pandas自带的生成日期距离的办法。咱们执行下方代码:
rng = pd.date_range('1/1/2021', periods=100, freq='S')pd.Series(np.random.randint(0, 500, len(rng)), index=rng)
date_range办法从2021年1月1日0秒开始,以1秒作为工夫距离执行100次时间段的划分。输入后果如下:
2021-01-01 00:00:00 4752021-01-01 00:00:01 1452021-01-01 00:00:02 132021-01-01 00:00:03 2402021-01-01 00:00:04 183 ... 2021-01-01 00:01:35 4132021-01-01 00:01:36 3302021-01-01 00:01:37 2722021-01-01 00:01:38 3042021-01-01 00:01:39 151Freq: S, Length: 100, dtype: int32
咱们将freq
的参数值从S(second)改为M(Month)试试看。
rng = pd.date_range('1/1/2021', periods=100, freq='M')pd.Series(np.random.randint(0, 500, len(rng)), index=rng)
输入:
2021-01-31 3112021-02-28 2562021-03-31 3272021-04-30 1512021-05-31 484 ... 2028-12-31 1702029-01-31 4922029-02-28 2052029-03-31 902029-04-30 446Freq: M, Length: 100, dtype: int32
咱们设置能够以季度作为频率进行日期生成。
prng = pd.period_range('2018Q1', '2020Q4', freq='Q-NOV')pd.Series(np.random.randn(len(prng)), prng)
输入2018第一季度到2020第四季度间的全副季度。
2018Q1 0.8330252018Q2 -0.5095142018Q3 -0.7355422018Q4 -0.2244032019Q1 -0.1197092019Q2 -1.3794132019Q3 0.8717412019Q4 0.8774932020Q1 0.5776112020Q2 -0.3657372020Q3 -0.4734042020Q4 0.529800Freq: Q-NOV, dtype: float64
3. 分类
Pandas有一种非凡的数据类型叫做"目录",即dtype="category",咱们依据将某些列设置为目录来进行分类。
筹备数据。
df = pd.DataFrame({"id": [1, 2, 3, 4, 5, 6], "raw_grade": ['a', 'b', 'b', 'a', 'a', 'e']})df
id | raw_grade | |
---|---|---|
0 | 1 | a |
1 | 2 | b |
2 | 3 | b |
3 | 4 | a |
4 | 5 | a |
5 | 6 | e |
咱们增加一个新列grade
并将它的数据类型设置为category
。
df["grade"] = df["raw_grade"].astype("category")df["grade"]
咱们能够看到grade
列只有3种值a,b,e。
0 a1 b2 b3 a4 a5 eName: grade, dtype: categoryCategories (3, object): ['a', 'b', 'e']
咱们按程序替换a、b、e为very good、good、very bad。
df["grade"].cat.categories = ["very good", "good", "very bad"]
此时的表格为:
id | raw_grade | grade | |
---|---|---|---|
0 | 1 | a | very good |
1 | 2 | b | good |
2 | 3 | b | good |
3 | 4 | a | very good |
4 | 5 | a | very good |
5 | 6 | e | very bad |
咱们对表格进行排序:
df.sort_values(by="grade", ascending=False)
id | raw_grade | grade | |
---|---|---|---|
5 | 6 | e | very bad |
1 | 2 | b | good |
2 | 3 | b | good |
0 | 1 | a | very good |
3 | 4 | a | very good |
4 | 5 | a | very good |
查看各类别的数量:
df.groupby("grade").size()
以上代码输入为:
gradevery good 3good 2very bad 1dtype: int64
4. IO
Pandas反对间接从文件中读写数据,如CSV、JSON、EXCEL等文件格式。Pandas反对的文件格式如下。
Format Type | Data Description | Reader | Writer |
---|---|---|---|
text | CSV | read_csv | to_csv |
text | Fixed-Width Text File | read_fwf | |
text | JSON | read_json | to_json |
text | HTML | read_html | to_html |
text | Local clipboard | read_clipboard | to_clipboard |
MS Excel | read_excel | to_excel | |
binary | OpenDocument | read_excel | |
binary | HDF5 Format | read_hdf | to_hdf |
binary | Feather Format | read_feather | to_feather |
binary | Parquet Format | read_parquet | to_parquet |
binary | ORC Format | read_orc | |
binary | Msgpack | read_msgpack | to_msgpack |
binary | Stata | read_stata | to_stata |
binary | SAS | read_sas | |
binary | SPSS | read_spss | |
binary | Python Pickle Format | read_pickle | to_pickle |
SQL | SQL | read_sql | to_sql |
SQL | Google BigQuery | read_gbq | to_gbq |
咱们仅以CSV文件为例作为解说。其余格局请参考上方表格。
咱们从CSV文件导入数据。大家不必特地在意下方网址的域名地址。
df = pd.read_csv("http://blog.caiyongji.com/assets/housing.csv")
查看前5行数据:
df.head(5)
longitude | latitude | housing_median_age | total_rooms | total_bedrooms | population | households | median_income | median_house_value | ocean_proximity | |
---|---|---|---|---|---|---|---|---|---|---|
0 | -122.23 | 37.88 | 41 | 880 | 129 | 322 | 126 | 8.3252 | 452600 | NEAR BAY |
1 | -122.22 | 37.86 | 21 | 7099 | 1106 | 2401 | 1138 | 8.3014 | 358500 | NEAR BAY |
2 | -122.24 | 37.85 | 52 | 1467 | 190 | 496 | 177 | 7.2574 | 352100 | NEAR BAY |
3 | -122.25 | 37.85 | 52 | 1274 | 235 | 558 | 219 | 5.6431 | 341300 | NEAR BAY |
4 | -122.25 | 37.85 | 52 | 1627 | 280 | 565 | 259 | 3.8462 | 342200 | NEAR BAY |
5. 绘图
Pandas反对matplotlib,matplotlib是功能强大的Python可视化工具。本节仅对Pandas反对的绘图办法进行简略介绍,咱们将会在下一篇文章中进行matplotlib的具体介绍。为了不错过更新,欢送大家关注我。
np.random.seed(999)df = pd.DataFrame(np.random.rand(10, 4), columns=['a', 'b', 'c', 'd'])
咱们间接调用plot
办法进行展现。
这里有两个须要留神的中央:
- 该plot办法是通过Pandas调用的plot办法,而非matplotlib。
- 咱们晓得Python语言是无需分号进行完结语句的。此处的分号示意执行绘图渲染后间接显示图像。
df.plot();
df.plot.bar();
df.plot.bar(stacked=True);
四、更多
咱们下篇将解说matplotlib的相干知识点,欢送关注机器学习前置教程系列,或我的集体博客http://blog.caiyongji.com/同步更新。