文章目录
- pandas基本数据结构
- Series:通过一维数组创建
- Series值的获取
- Series的运算
- Series缺失值检测
- Series自动对齐
- Series及其索引的name属性
- DataFrame: 通过二维数组创建
- DataFrame: 通过字典的方式创建
- 索引对象
- DataFrame数据获取
- pandas基本功能
- pandas:数据文件读取
- pandas:数据过滤获取
- pandas:缺省值NaN处理方法
- pandas:常用的数学统计方法
- pandas:唯一值、值计数以及成员资格
- pandas:层次索引
- pandas:按照层次索引进行统计数据
pandas基本数据结构
- pandas中主要有两种数据结构,分别是:Series和DataFrame。
- Series:一种类似于一维数组的对象,是由一组数据(各种NumPy数据类型)以及一组与之相关的数据标签(即索引)组成。仅由一组数据也可产生简单的Series对象。注意:Series中的索引值是可以重复的。
- DataFrame:一个表格型的数据结构,包含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔型等),DataFrame即有行索引也有列索引,可以被看做是由Series组成的字典。
Series:通过一维数组创建
import numpy as np
from pandas import Series, DataFrame
import pandas as pd
arr = np.array([1,3,5,np.NaN,10])
series01 = Series(arr)
series01
0 1.0
1 3.0
2 5.0
3 NaN
4 10.0
dtype: float64
series02 = Series([87,90,89])
series02
0 87
1 90
2 89
dtype: int64
series02.index=[u'语文',u'数学',u'英语']
series02
语文 87
数学 90
英语 89
dtype: int64
series03 = Series(data=[87,90,89],dtype=np.float64,index=[u'语文',u'数学',u'英语'])
series03
语文 87.0
数学 90.0
英语 89.0
dtype: float64
dict1 = {'name':'Twiss','university':'CMU','degree':'graduate'}
series04 = Series(dict1)
series04
name Twiss
university CMU
degree graduate
dtype: object
Series值的获取
Series值的获取主要有两种方式:
- 通过方括号+索引的方式读取对应索引的数据,有可能返回多条数据
- 通过方括号+下标值的方式读取对应下标值的数据,下标值的取值范围为:[0,len(Series.values));另外下标值也可以是负数,表示从右往左获取数据
Series获取多个值的方式类似NumPy中的ndarray的切片操作,通过方括号+下标值/索引值+冒号(:)的形式来截取series对象中的一部分数据。
Series的运算
NumPy中的数组运算,在Series中都保留了,均可以使用,并且Series进行数组运算的时候,索引与值之间的映射关系不会发生改变。
注意:其实在操作Series的时候,基本上可以把Series看成NumPy中的ndarray数组来进行操作。ndarray数组的绝大多数操作都可以应用到Series上。
series = Series({'001':879,'002':888,'003':897})
series
001 879
002 888
003 897
dtype: int64
series[series>880]
002 888
003 897
dtype: int64
series/100
001 8.79
002 8.88
003 8.97
dtype: float64
series2 = Series([-1,-2,3,4])
series2
0 -1
1 -2
2 3
3 4
dtype: int64
np.exp(series2)
0 0.367879
1 0.135335
2 20.085537
3 54.598150
dtype: float64
np.fabs(series2)
0 1.0
1 2.0
2 3.0
3 4.0
dtype: float64
Series缺失值检测
scores = Series({"Twiss":90,"Evan":89,"Iran":86})
scores
Twiss 90
Evan 89
Iran 86
dtype: int64
new_index = ["Twiss","Max","Evan","Iran"]
scores=Series(scores,index=new_index)
scores
Twiss 90.0
Max NaN
Evan 89.0
Iran 86.0
dtype: float64
pandas中的isnull和notnull两个函数可以用于在Series中检测缺失值,这两个函数的返回时一个布尔类型的Series
pd.isnull(scores)
Twiss False
Max True
Evan False
Iran False
dtype: bool
pd.notnull(scores)
Twiss True
Max False
Evan True
Iran True
dtype: bool
scores[pd.isnull(scores)]
Max NaN
dtype: float64
scores[pd.notnull(scores)]
Twiss 90.0
Evan 89.0
Iran 86.0
dtype: float64
Series自动对齐
当多个series对象之间进行运算的时候,如果不同series之间具有不同的索引值,那么运算会自动对齐不同索引值的数据,如果某个series没有某个索引值,那么最终结果会赋值为NaN。
s1 = Series([12,23,45],index=['p1','p2','p3'])
s2 = Series([54,43,32,21],index=['p2','p3','p4','p5'])
s1+s2
p1 NaN
p2 77.0
p3 88.0
p4 NaN
p5 NaN
dtype: float64
s1*s2
p1 NaN
p2 1242.0
p3 1935.0
p4 NaN
p5 NaN
dtype: float64
s1/s2
p1 NaN
p2 0.425926
p3 1.046512
p4 NaN
p5 NaN
dtype: float64
Series及其索引的name属性
Series对象本身以及索引都具有一个name属性,默认为空,根据需要可以进行赋值操作
scores = Series({"Twiss":99,"Evan":88,"Iran":85})
scores.name = u'语文'
scores.index.name = u'考试成绩'
scores
考试成绩
Twiss 99
Evan 88
Iran 85
Name: 语文, dtype: int64
DataFrame: 通过二维数组创建
df01 = DataFrame(["Twiss","Rvan","Wind"],[99,70,88])
df01
|
0 |
99 |
Twiss |
70 |
Rvan |
88 |
Wind |
df02 = DataFrame([
['Twiss',99],
['Rvan',70],
['Wind',88]
],columns=[u'姓名',u'成绩'])
df02
|
姓名 |
成绩 |
0 |
Twiss |
99 |
1 |
Rvan |
70 |
2 |
Wind |
88 |
df02.columns
Index(['姓名', '成绩'], dtype='object')
df02.index
RangeIndex(start=0, stop=3, step=1)
df02.values
array([['Twiss', 99],
['Rvan', 70],
['Wind', 88]], dtype=object)
DataFrame: 通过字典的方式创建
data = {
"name":["Twiss","Evan","Wind","Like","Cliera"],
"score":[998,887,897,878,777],
"year":2019
}
df = DataFrame(data)
df
|
name |
score |
year |
0 |
Twiss |
998 |
2019 |
1 |
Evan |
887 |
2019 |
2 |
Wind |
897 |
2019 |
3 |
Like |
878 |
2019 |
4 |
Cliera |
777 |
2019 |
df.index=["one","two","three","four","five"]
df
|
name |
score |
year |
one |
Twiss |
998 |
2019 |
two |
Evan |
887 |
2019 |
three |
Wind |
897 |
2019 |
four |
Like |
878 |
2019 |
five |
Cliera |
777 |
2019 |
索引对象
- 不管是Series还是DataFrame对象,都有索引对象。
- 索引对象负责管理轴标签和其它元数据(eg:轴名称等等)
- 通过索引可以从Series、DataFrame中获取值或者对某个索引值进行重新赋值
- Series或者DataFrame的自动对齐功能是通过索引实现的
DataFrame数据获取
- 可以直接通过列索引获取指定列的数据, eg: df[column_name]
- 如果需要获取指定行的数据的话,需要通过ix方法来获取对应行索引的行数据,eg: df.ix[index_name]
df
|
name |
score |
year |
one |
Twiss |
998 |
2019 |
two |
Evan |
887 |
2019 |
three |
Wind |
897 |
2019 |
four |
Like |
878 |
2019 |
five |
Cliera |
777 |
2019 |
df["year"]
one 2019
two 2019
three 2019
four 2019
five 2019
Name: year, dtype: int64
df.loc['one']
name Twiss
score 998
year 2019
Name: one, dtype: object
df['score']=[990,888,890,870,770]
df['university'] = np.NaN
df.loc['five'] = np.NaN
df
|
name |
score |
year |
university |
one |
Twiss |
990.0 |
2019.0 |
NaN |
two |
Evan |
888.0 |
2019.0 |
NaN |
three |
Wind |
890.0 |
2019.0 |
NaN |
four |
Like |
870.0 |
2019.0 |
NaN |
five |
NaN |
NaN |
NaN |
NaN |
pandas基本功能
- 数据文件读取/文本数据读取
- 索引、选取和数据过滤
- 算法运算和数据对齐
- 函数的应用和映射
- 重置索引
pandas:数据文件读取
通过pandas提供的read_xxx相关的函数可以读取文件中的数据,并形成DataFrame,常用的数据读取方法为:read_csv,主要可以读取文本类型的数据
df = pd.read_csv("data1.csv")
df
|
name |
age |
score |
0 |
Twiss |
24 |
99 |
1 |
Wind |
22 |
98 |
2 |
Evan |
25 |
97 |
df = pd.read_csv("data2.text",sep=';',header=None)
df
|
0 |
1 |
2 |
3 |
4 |
0 |
Twiss |
24 |
99 |
98 |
78 |
1 |
Wind |
25 |
98 |
97 |
77 |
2 |
Evan |
22 |
97 |
55 |
67 |
pandas:数据过滤获取
通过DataFrame的相关方式可以获取对应的列或者数据形成一个新的DataFrame, 方便后续进行统计计算。
columns = ['name','age',u'高等数学',u'线性代数',u'离散数学']
df.columns = columns
df
|
name |
age |
高等数学 |
线性代数 |
离散数学 |
0 |
Twiss |
24 |
99 |
98 |
78 |
1 |
Wind |
25 |
98 |
97 |
77 |
2 |
Evan |
22 |
97 |
55 |
67 |
pandas:缺省值NaN处理方法
对于DataFrame/Series中的NaN一般采取的方式为删除对应的列/行或者填充一个默认值
- dropna:根据标签的值中是否存在缺失数据对轴标签进行过滤(删除), 可以通过阈值的调节对缺失值的容忍度
- fillna:用指定值或者插值的方式填充缺失数据,比如: ffill或者bfill
- isnull:返回一个含有布尔值的对象,这些布尔值表示那些值是缺失值NA
- notnull: isnull的否定式
df2 = DataFrame([
['Twiss',np.NaN,667,'M'],
['JackSon',np.NaN,np.NaN,np.NaN],
['Evan',23,np.NaN,'M'],
['Wind',18,555,'F']
],columns=['name','age','salary','gender'])
df2
|
name |
age |
salary |
gender |
0 |
Twiss |
NaN |
667.0 |
M |
1 |
JackSon |
NaN |
NaN |
NaN |
2 |
Evan |
23.0 |
NaN |
M |
3 |
Wind |
18.0 |
555.0 |
F |
df2.isnull()
|
name |
age |
salary |
gender |
0 |
False |
True |
False |
False |
1 |
False |
True |
True |
True |
2 |
False |
False |
True |
False |
3 |
False |
False |
False |
False |
df2.notnull()
|
name |
age |
salary |
gender |
0 |
True |
False |
True |
True |
1 |
True |
False |
False |
False |
2 |
True |
True |
False |
True |
3 |
True |
True |
True |
True |
df2.dropna()
|
name |
age |
salary |
gender |
3 |
Wind |
18.0 |
555.0 |
F |
df2.dropna(how='all')
|
name |
age |
salary |
gender |
0 |
Twiss |
NaN |
667.0 |
M |
1 |
JackSon |
NaN |
NaN |
NaN |
2 |
Evan |
23.0 |
NaN |
M |
3 |
Wind |
18.0 |
555.0 |
F |
df2.dropna(axis=1)
|
name |
0 |
Twiss |
1 |
JackSon |
2 |
Evan |
3 |
Wind |
df = DataFrame(np.random.randn(7,3))
df.loc[:4,1] = np.nan
df.loc[:2,2] = np.nan
df
|
0 |
1 |
2 |
0 |
-0.393950 |
NaN |
NaN |
1 |
-1.449680 |
NaN |
NaN |
2 |
-1.000118 |
NaN |
NaN |
3 |
-0.825733 |
NaN |
-1.925034 |
4 |
2.357290 |
NaN |
-0.080654 |
5 |
-0.622228 |
2.597366 |
-1.435983 |
6 |
0.979495 |
1.310981 |
-0.304767 |
df.fillna(0)
|
0 |
1 |
2 |
0 |
-0.393950 |
0.000000 |
0.000000 |
1 |
-1.449680 |
0.000000 |
0.000000 |
2 |
-1.000118 |
0.000000 |
0.000000 |
3 |
-0.825733 |
0.000000 |
-1.925034 |
4 |
2.357290 |
0.000000 |
-0.080654 |
5 |
-0.622228 |
2.597366 |
-1.435983 |
6 |
0.979495 |
1.310981 |
-0.304767 |
df.fillna({1:0.5,2:-1,3:1})
|
0 |
1 |
2 |
0 |
-0.393950 |
0.500000 |
-1.000000 |
1 |
-1.449680 |
0.500000 |
-1.000000 |
2 |
-1.000118 |
0.500000 |
-1.000000 |
3 |
-0.825733 |
0.500000 |
-1.925034 |
4 |
2.357290 |
0.500000 |
-0.080654 |
5 |
-0.622228 |
2.597366 |
-1.435983 |
6 |
0.979495 |
1.310981 |
-0.304767 |
pandas:常用的数学统计方法
- count 计算非NA值的数量
- describe 针对Series或各DataFrame列计算总统计值
- min/max 计算最大值、最小值
- idxmin、idxmax 计算能够获取到最小值和最大值的索引位置(整数)
- idxmin、idxmaxe’zui’da’zhi 计算能够获取到最小值和最大值的索引值
- quantile 计算样本的分位数(0到1)
- sum 值的总和
- mean 值的平均数
- median 值的中位数
- mad 根据平均值计算平均绝对距离差
- var 样本数值的方差
- std 样本值的标准差
- cumsum 样本值的累计和
- cummin、cummax 样本的累计最小值、最大值
- cumprod 样本值的累计积
- pct_change 计算百分数变化
df = DataFrame({
'GDP':[900,1000,1100,1200,1300],
'Output_count':[300,400,500,550,600],
'Year':['2012','2013','2014','2015','2016']
})
df
|
GDP |
Output_count |
Year |
0 |
900 |
300 |
2012 |
1 |
1000 |
400 |
2013 |
2 |
1100 |
500 |
2014 |
3 |
1200 |
550 |
2015 |
4 |
1300 |
600 |
2016 |
df.cov()
|
GDP |
Output_count |
GDP |
25000.0 |
18750.0 |
Output_count |
18750.0 |
14500.0 |
pandas:相关系数与协方差
协方差
如果有X,Y两个变量,每个时刻的“X值与其均值之差”乘以“Y值与其均值之差”得到一个乘积,再对这每时刻的乘积求和并求出均值。
如果协方差为正,说明X,Y同向变化,协方差越大说明同向程度越高;如果协方差为负,说明X,Y反向运动,协方差越小说明反向程度越高。
df['GDP'].cov(df['Output_count'])
18750.0
相关系数
就是用X、Y的协方差除以X的标准差和Y的标准差。所以,相关系数也可以看成协方差:一种剔除了两个变量量纲影响、标准化后的特殊协方差。
1.也可以反映两个变量变化时是同向还是反向,如果同向变化为正,反向变化为负
2.由于它是标准化后的协方差,因此更重的特性是,它消除了两个变量变化幅度的影响,而只是单纯反应两个变量单位变化的相似程度。
注意:
相关系数不像协方差一样可以在 + ∞ +\infty +∞ 到 - ∞ -\infty -∞ 间变化,它只能在+1到-1之间变化
当相关系数为1的时候两者相识度最大,同向正相关
当相关系数为0的时候两者没有任何相似度,两个变量无关
df.corr()
|
GDP |
Output_count |
GDP |
1.000000 |
0.984798 |
Output_count |
0.984798 |
1.000000 |
df['GDP'].corr(df['Output_count'])
0.9847982464479191
pandas:唯一值、值计数以及成员资格
- unique方法用于获取Series中的唯一值数组(去重数据后的数组)
- value_counts方法用于计算一个Series中各值的出现频率
- isin方法用于判断矢量化集合的成员资格,可用于选取Series中或者DataFrame中列中数据的子集
ser = Series(['a','b','c','a'])
ser
0 a
1 b
2 c
3 a
dtype: object
ser.unique()
array(['a', 'b', 'c'], dtype=object)
df = DataFrame({
"order_id":['1001','1002','1003','1004','1005'],
"member_id":['m01','m02','m01','m03','mo4'],
"order_amount":[111,222,333,444,555]
})
df
|
order_id |
member_id |
order_amount |
0 |
1001 |
m01 |
111 |
1 |
1002 |
m02 |
222 |
2 |
1003 |
m01 |
333 |
3 |
1004 |
m03 |
444 |
4 |
1005 |
mo4 |
555 |
df["member_id"].unique()
array(['m01', 'm02', 'm03', 'mo4'], dtype=object)
ser.value_counts()
a 2
b 1
c 1
dtype: int64
ser.value_counts(ascending=False)
a 2
b 1
c 1
dtype: int64
mask = ser.isin(['b','c'])
mask
0 False
1 True
2 True
3 False
dtype: bool
ser[mask]
1 b
2 c
dtype: object
pandas:层次索引
- 在某一个方向拥有多个(两个及两个以上)索引级别
- 通过层次化索引,pandas能够以较低维度形式处理高纬度的数据
- 通过层次化索引,可以按照层次统计数据
- 层次索引包括Series层次索引和DataFrame层次索引
data = pd.Series([100,200,122,150,180],index=[['2019','2019','2019','2018','2018'],
['apple','banana','orange','apple','orange']])
data
2019 apple 100
banana 200
orange 122
2018 apple 150
orange 180
dtype: int64
data['2019']
apple 100
banana 200
orange 122
dtype: int64
data[:,'apple']
2019 100
2018 150
dtype: int64
data01 = data.swaplevel().sort_index()
data01
apple 2018 150
2019 100
banana 2019 200
orange 2018 180
2019 122
dtype: int64
data02 = data.unstack(level=1)
data02
|
apple |
banana |
orange |
2018 |
150.0 |
NaN |
180.0 |
2019 |
100.0 |
200.0 |
122.0 |
data02 = data.unstack(level=0)
data02
|
2018 |
2019 |
apple |
150.0 |
100.0 |
banana |
NaN |
200.0 |
orange |
180.0 |
122.0 |
df = DataFrame({
'year':[2018,2018,2018,2019,2019],
'fruit':['apple','banana','apple','banana','apple'],
'account':[2345,3214,4444,5555,2234],
'profit':[111,222,333,444,555]
})
df
|
year |
fruit |
account |
profit |
0 |
2018 |
apple |
2345 |
111 |
1 |
2018 |
banana |
3214 |
222 |
2 |
2018 |
apple |
4444 |
333 |
3 |
2019 |
banana |
5555 |
444 |
4 |
2019 |
apple |
2234 |
555 |
df = df.set_index(['year','fruit'])
df
|
|
account |
profit |
year |
fruit |
|
|
2018 |
apple |
2345 |
111 |
banana |
3214 |
222 |
apple |
4444 |
333 |
2019 |
banana |
5555 |
444 |
apple |
2234 |
555 |
df.loc[2018,'banana']
/usr/local/Cellar/ipython/7.8.0/libexec/vendor/lib/python3.7/site-packages/ipykernel_launcher.py:1: PerformanceWarning: indexing past lexsort depth may impact performance.
"""Entry point for launching an IPython kernel.
|
|
account |
profit |
year |
fruit |
|
|
2018 |
banana |
3214 |
222 |
pandas:按照层次索引进行统计数据
df.sum(level='year')
|
account |
profit |
year |
|
|
2018 |
10003 |
666 |
2019 |
7789 |
999 |
df.mean(level='fruit')
|
account |
profit |
fruit |
|
|
apple |
3007.666667 |
333.0 |
banana |
4384.500000 |
333.0 |
df.min(level=['year','fruit'])
|
|
account |
profit |
year |
fruit |
|
|
2018 |
apple |
2345 |
111 |
banana |
3214 |
222 |
2019 |
banana |
5555 |
444 |
apple |
2234 |
555 |