pandas主要用来做数据分析,是基于Numpy的一种工具。主要的数据结构有两种:(1)Series,(2)DataFrame。
一、数据结构简介:DataFrame和Series
序列Series:一维数组,类似于Numpy中的一维array和Python基本的数据结构List,其区别是:List中的元素可以是不同的数据类型,而Array和Series中则只允许存储相同的数据类型,这样可以更有效的使用内存,提高运算效率。
数据框DataFrame:二维的表格型数据结构。
Series创建的三种方式:
- 通过Numpy的一维数组创建:
>>> import numpy
>>> import pandas
>>> arr1=numpy.arange(10)
>>> s1=pandas.Series(arr1)
>>> s1
0 0
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
创建时自动添加索引,从0开始。可以通过s1.index查看Series的索引:
>>> s1.index
RangeIndex(start=0, stop=10, step=1)
还可以通过s1.values查看数据值:
>>> s1.values
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
Series也可以自定义索引,通过自定义的索引来获取值或者修改值。
>>> s1=pandas.Series([0,1,2,3,4,5,6,7,8,9],index=['a','b','c','d','e','f','g','h','i','j'])
>>> s1
a 0
b 1
c 2
d 3
e 4
f 5
g 6
h 7
i 8
j 9
dtype: int64
>>> s1['a'] #获取值
0
>>> s1['a']=34 #修改值
>>> s1
a 34
b 1
c 2
d 3
e 4
f 5
g 6
h 7
i 8
j 9
dtype: int64
这个自定义索引就类似于python中的字典,故我们可以采用字典去创建Series:字典的key就是series的自定义索引,字典的value就是Series的值。如下所示
2. 通过字典创建
>>> dict1={'a':1,'b':2,'c':3,'d':4}
>>> s2=pandas.Series(dict1)
>>> s2
a 1
b 2
c 3
d 4
dtype: int64
此时,索引依然可以自定义。如果自定义了索引,自定的索引会自动寻找原来的索引,如果一样的,就取原来索引对应的值,这个可以简称为“自动对齐”。
>>> s3=pandas.Series(s2,index=['df','b','c','d'])
>>> s3
df NaN
b 2.0
c 3.0
d 4.0
dtype: float64
如果没有值,都对齐赋给 NaN
Pandas 有专门的方法来判断值是否为空。Series 对象也有同样的方法:
>>> s3.isnull()
df True
b False
c False
d False
dtype: bool
索引的名字,是可以从新定义的:
>>> s5.index=['v','n','k','l']
>>> s5
v NaN
n 1.0
k 2.0
l 3.0
dtype: float64
3.通过DataFrame中某一行或某一列创建
DataFrame的三种创建方式
DataFrame是一种二维的数据结构,非常接近于电子表格或者类似 mysql 数据库的形式,竖行称之为 column,横行称之为 index。
- 通过二维数组创建
>>> arr1=numpy.array(numpy.arange(12)).reshape(4,3)
>>> df1=pandas.DataFrame(arr1)
>>> df1
0 1 2
0 0 1 2
1 3 4 5
2 6 7 8
3 9 10 11
- 通过字典创建
>>> dict2={'a':[0,1,2],'b':[3,4,5],'c':[6,7,8],'d':[9,10,11]}
>>> df2=pandas.DataFrame(dict2)
>>> df2
a b c d
0 0 3 6 9
1 1 4 7 10
2 2 5 8 11
- 通过数据框创建
>>> df=s4[['a','b']]
>>> df
a b
0 0 3
1 1 4
2 2 5
二、查询数据
这里的查询数据相当于R语言里的subset功能,可以通过布尔索引有针对的选取原数据的子集、指定行、指定列等。
- 导入一个student数据集:
student = pd.io.parsers.read_csv(‘C:\Users\admin\Desktop\student.csv’) - 查询数据的前5行或末尾5行:
student.head()
student.tail() - 查询指定的行
student.ix[[0,2,4,6,8]] #ix索引标签函数必须是中括号[] - 查询指定的列
student[[‘Name’,‘Height’,‘Weight’]].head() #如果多个列的话,必须使用双重中括号。 - 通过ix索引标签查询指定的列
student.ix[:,[‘Name’,‘Height’,‘Weight’]].head() - 查询指定的行和列
student.ix[[0,2,4,5,7],[‘Name’,‘Height’,‘Weight’]].head()
通过布尔索引实现数据的子集查询。 - 查询所有女生的信息
student[student[‘Sex’]==‘F’] - 查询出所有12岁以上的女生信息
student[(student[‘Sex’]==‘F’) & (student[‘Age’]>12)] - 查询出所有12岁以上的女生姓名、身高和体重
student[(student[‘Sex’]==‘F’) & (student[‘Age’]>12)][[‘Name’,‘Height’,‘Weight’]]
上面的查询逻辑其实非常的简单,需要注意的是,如果是多个条件的查询,必须在&(且)或者|(或)的两端条件用括号括起来。
三、统计分析
np.random.seed(1234)
d1 = pd.Series(2*np.random.normal(size=100)+3)
d2 = np.random.f(2,4,size=100)
d3 = np.random.ranint(1,100,size=100)
d1.count()
d1.min()
d1.max()
d1.idxmin()
d1.idxmax()
d1.quantile(0.1) #10%分位数
d1.sum()
d1.mean()
d1.median() #中位数
d1.mode() #众数
d1.var() #方差
d1.std()
d1.mad() #平均绝对偏差
d1.skew() #偏度
d1.kurt() #峰度
d1.describe() #一次性输出多个描述性统计指标
四、SQL操作:增删改查
增:
新建一个数据框student1:
>>> dic1 = {'Name':['Liu','Zhang'],
'Sex':['M','F'],'Age':[27,23],
'Height':[165.7,167.2],'Weight':[61,63]}
>>> student1 = pd.DataFrame(dic1)
>>> student1
Name Sex Age Height Weight
0 Liu M 27 165.7 61
1 Zhang F 23 167.2 63
新建一个数据框student2:
>>> dic2 = {'Name':['Liusi','Zhangsan'],
'Sex':['M','F'],'Age':[29,20],
'Height':[168.7,167.2],'Weight':[51,33]}
>>> student2 = pd.DataFrame(dic2)
>>> syudent2
Name Sex Age Height Weight
0 Liusi M 29 168.7 51
1 Zhangsan F 20 167.2 33
将student1中的数据增加到student2中:通过concat函数实现增加新行,并且concat可以自动对齐变量
>>> student3= pd.concat([student2, student1])
>>> student3
Name Sex Age Height Weight
0 Liusi M 29 168.7 51
1 Zhangsan F 20 167.2 33
0 Liu M 27 165.7 61
1 Zhang F 23 167.2 63
新增列:
>>> pd.DataFrame(student3, columns=['Name', 'Sex', 'Age', 'Height', 'Weight', 'Score'])
Name Sex Age Height Weight Score
0 Liusi M 29 168.7 51 NaN
1 Zhangsan F 20 167.2 33 NaN
0 Liu M 27 165.7 61 NaN
1 Zhang F 23 167.2 63 NaN
删
通过del命令:删除数据框。
删除指定行:
student1.drop([0])
删除符合条件的行:
student1.drop(['Age']>50)
删除列:
>>> student1.drop(['Name'],axis=1).head()
不论是删除行还是删除列,都可以通过drop方法实现,只需要设定好删除的轴即可,即调整drop方法中的axis参数。默认该参数为0,表示删除行观测,如果需要删除列变量,则需设置为1。
改
>>> student1.ix[student1['Name']=='Liu','Height']=170
聚合:pandas模块中可以通过groupby()函数实现数据的聚合操作
根据性别分组,计算各组别中学生身高和体重的平均值:
>>> student1.groupby('Sex').mean()
Sex
F 21.5 167.2 48.0
M 28.0 167.2 56.0
排序:
排序在日常的统计分析中还是比较常见的操作,我们可以使用order、sort_index和sort_values实现序列和数据框的排序工作:
>>> student3.sort_values(by=['Sex', 'Age'])
Name Sex Age Height Weight
1 Zhangsan F 20 167.2 33
1 Zhang F 23 167.2 63
0 Liu M 27 165.7 61
0 Liusi M 29 168.7 51
多表连接:
多表之间的连接也是非常常见的数据库操作,连接分内连接和外连接,在数据库语言中通过join关键字实现,pandas使用merger函数实现数据的各种连接操作,merge函数实现的是两个表之间的内连接,即返回两张表中共同部分的数据。可以通过how参数设置连接的方式,left为左连接;right为右连接;outer为外连接。
>>> dic3 = {'Name':['Liu','Zhang','Liusi','Zhangsan'],
'Score':['88', '99', '67', '89']}
>>.> score = pd.DataFrame(dic3)
>>> stu_scorel = pd.merge(student3, score, on='Name',how='left')
Name Sex Age Height Weight Score
0 Liusi M 29 168.7 51 67
1 Zhangsan F 20 167.2 33 89
2 Liu M 27 165.7 61 88
3 Zhang F 23 167.2 63 99
五、缺失值处理
现实生活中的数据是非常杂乱的,其中缺失值也是非常常见的,对于缺失值的存在可能会影响到后期的数据分析或挖掘工作,那么我们该如何处理这些缺失值呢?常用的有三大类方法,即删除法、填补法和插值法。
- 删除法:当数据中的某个变量大部分值都是缺失值,可以考虑删除改变量;当缺失值是随机分布的,且缺失的数量并不是很多是,也可以删除这些缺失的观测。
sum函数和isnull函数来检测数据中含有多少缺失值,dropna会删除任何含有缺失值的行,如果使用参数how=’all’,则表明只删除所有行为缺失值的观测 - 替补法:对于连续型变量,如果变量的分布近似或就是正态分布的话,可以用均值替代那些缺失值;如果变量是有偏的,可以使用中位数来代替那些缺失值;对于离散型变量,我们一般用众数去替换那些存在缺失的观测。
使用一个常量来填补缺失值,可以使用fillna函数实现简单的填补工作:
df.fillna(0) #0填补
df.fillna(method='ffill') #前项填补
df.fillna(method='bfill') #后项填补
插补法:插补法是基于蒙特卡洛模拟法,结合线性模型、广义线性模型、决策树等方法计算出来的预测值替换缺失值。
数据透视表
pandas为我们提供了非常强大的函数pivot_table(),该函数就是实现数据透视表功能的。对于上面所说的一些聚合函数,可以通过参数aggfunc设定。函数的语法和参数:
pivot_table(data,values=None,
index=None,
columns=None,
aggfunc='mean',
fill_value=None,
margins=False,
dropna=True,
margins_name='All')
data:需要进行数据透视表操作的数据框
values:指定需要聚合的字段
index:指定某些原始变量作为行索引
columns:指定哪些离散的分组变量
aggfunc:指定相应的聚合函数
fill_value:使用一个常数替代缺失值,默认不替换
margins:是否进行行或列的汇总,默认不汇总
dropna:默认所有观测为缺失的列
margins_name:默认行汇总或列汇总的名称为’All’