目录
一、Pandas简介
数据结构
二、Series
series 的创建
Series值的获取
Series的运算
Series缺失值检测
Series自动对齐
Series及其索引的name属性
三、DataFrame
创建
Index对象
通过索引值或索引标签获取数据
自动化对齐
四、文件操作
文件读取
数据库数据读取
将数据写出为csv
将数据写出为excel
将数据写入数据库
五、查询数据
通过布尔索引来实现特定信息的查询
六、统计分析
七、类似于SQL的操作
增:
删
改:
分组聚合:groupby()函数
排序:
多表连接:
八、缺失值处理
删除法:直接删除缺失值
用常数填补所有缺失值
采用前项填充或后向填充
使用常量填充不同的列
用均值或中位数填充各自的列
九、数据透视表
多层索引的使用
Numpy,Scipy,pandas三个库的区别
- NumPy:数学计算库,以矩阵为基础的数学计算模块,包括基本的四则运行,方程式以及其他方面的计算什么的,纯数学;
- SciPy :科学计算库,有一些高阶抽象和物理模型,在NumPy基础上,封装了一层,没有那么纯数学,提供方法直接计算结果;比如:做个傅立叶变换,这是纯数学的,用Numpy;做个滤波器,这属于信号处理模型了,用Scipy。
- Pandas:提供名为DataFrame的数据结构,比较契合统计分析中的表结构,做数据分析用的,主要是做表格数据呈现。
目前来说,随着 Pandas 更新,Numpy 大部分功能已经直接和 Pandas 融合了。
一、Pandas简介
Python Data Analysis Library 或 pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。Pandas 纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的工具。pandas提供了大量能使我们快速便捷地处理数据的函数和方法。你很快就会发现,它是使Python成为强大而高效的数据分析环境的重要因素之一。
Pandas是python的一个数据分析包,最初由AQR Capital Management于2008年4月开发,并于2009年底开源出来,目前由专注于Python数据包开发的PyData开发team继续开发和维护,属于PyData项目的一部分。Pandas最初被作为金融数据分析工具而开发出来,因此,pandas为时间序列分析提供了很好的支持。 Pandas的名称来自于面板数据(panel data)和python数据分析(data analysis)。panel data是经济学中关于多维数据集的一个术语,在Pandas中也提供了panel的数据类型。
数据结构
- Series:一维数组,与Numpy中的一维array类似。二者与Python基本的数据结构List也很相近,其区别是:List中的元素可以是不同的数据类型,而Array和Series中则只允许存储相同的数据类型,这样可以更有效的使用内存,提高运算效率。
- Time- Series:以时间为索引的Series。
- DataFrame:二维的表格型数据结构。很多功能与R中的data.frame类似。可以将DataFrame理解为Series的容器。以下的内容主要以DataFrame为主。
- Panel :三维的数组,可以理解为DataFrame的容器。
Pandas 有两种自己独有的基本数据结构。虽然它有着两种数据结构,但它依然是 Python 的一个库,所以,Python 中有的数据类型在这里依然适用,也同样还可以使用类自己定义数据类型。只不过,Pandas 里面又定义了两种数据类型:Series 和 DataFrame,它们让数据操作更简单了。
二、Series
Series 在python的中type()为 <class 'pandas.core.series.Series'>。
series 的创建
- 通过一维数组创建,如果没有为数据指定索引值,会自动创建一个0-N-1的索引
- 通过字典的方式创建,字典的key为索引
# series 的创建:数组方式
arr=np.array([1,3,5,np.NaN,10])
ser1=pd.Series(arr)
print(ser1)
print(ser1.dtype) # 获取series的元素的数据类型
print(ser1.index) # 获取series的索引
print(ser1.values) # 获取series的值
0 1.0
1 3.0
2 5.0
3 NaN
4 10.0
dtype: float64
float64
RangeIndex(start=0, stop=5, step=1)
[ 1. 3. 5. nan 10.]# 通过index修改索引值,且索引值可以重复
ser2=pd.Series([98,99,90])
ser2.index=['语文','数学','语文']
print(ser2)
ser3=pd.Series(data=[99,98,97],dtype=np.float64,index=['语文','数学','历史'])
print(ser3)
语文 98
数学 99
语文 90
dtype: int64
语文 99.0
数学 98.0
历史 97.0
dtype: float64# 通过字典的方式创建series,字典的key为series的索引值,字典的values为series的元素值
dit={'语文':90,'数学':99,'历史':98}
ser4=pd.Series(dit)
print(ser4)
历史 98
数学 99
语文 90
dtype: int64
Series值的获取
Series值的获取主要有两种方式:
- 通过方括号+索引的方式读取对应索引的数据,有可能返回多条数据
- 通过方括号+下标值的方式读取对应下标值的数据,下标值的取值范围为:[0,len(Series.values)];另外下标值也可 以是负数,表示从右往左获取数据
Series获取多个值的方式类似NumPy中的ndarray的切片操作,通过方括号+下标值/索引值+冒号(:)的形式来截取series对象中的一部分数据!
# Series数据的获取:下标值、索引值、切片
print('==============ser4[1]==============')
print(ser4[1])
print('==============ser4["语文"]=========')
print(ser4["语文"])
print('==============ser4[0:2]============')
print(ser4[0:2])
print("==============ser4['历史':'语文']===")
print(ser4['历史':'语文'])
==============ser4[1]==============
99
==============ser4["语文"]=========
90
==============ser4[0:2]============
历史 98
数学 99
dtype: int64
==============ser4[u'历史':u'语文']===
历史 98
数学 99
语文 90
dtype: int64
Series的运算
NumPy中的数组运算,在Series中都保留了,均可以使用,并且Series进行数组运算的时候,索引与值之间的映射关系不会发生改变。
注意:其实在操作Series的时候,基本上可以把Series看成NumPy中的ndarray数组来进行操作。ndarray数组的绝大多数操作都可以应用到Series上。
# series的部分运算
print('==============ser4[ser4>98] 布尔运算=========')
print(ser4[ser4>98])
print('==============ser4/9 除法运算================')
print(ser4/9)
print('==============np.exp(ser4) e的x次方==========')
print(np.exp(ser4))
print('==============np.log10(ser4) ========')
print(np.log10(ser4))
==============ser4[ser4>98] 布尔运算=========
数学 99
dtype: int64
==============ser4/9 除法运算================
历史 10.888889
数学 11.000000
语文 10.000000
dtype: float64
==============np.exp(ser4) e的x次方==========
历史 3.637971e+42
数学 9.889030e+42
语文 1.220403e+39
dtype: float64
==============np.log10(ser4) ========
历史 1.991226
数学 1.995635
语文 1.954243
dtype: float64# 在pandas中用NaN表示一个缺省值或者NA值
print('==============ser4================')
print(ser4)
ser5=pd.Series(ser4,index=['地理','语文','历史','数学'])
print('==============ser5================')
print(ser5)
==============ser4================
历史 98
数学 99
语文 90
dtype: int64
==============ser5================
地理 NaN
语文 90.0
历史 98.0
数学 99.0
dtype: float64
Series缺失值检测
pandas中的isnull和notnull两个函数可以用于在Series中检测缺失值,这两个函数的返回时一个布尔类型的Series
print('==============pd.isnull(ser5)================')
print(pd.isnull(ser5))
print('==============ser5[pd.isnull(ser5)]===========')
print(ser5[pd.isnull(ser5)])
print('==============pd.notnull(ser5)================')
print(pd.notnull(ser5))
print('==============ser5[pd.notnull(ser5)]==========')
print(ser5[pd.notnull(ser5)])
==============pd.isnull(ser5)================
地理 True
语文 False
历史 False
数学 False
dtype: bool
==============ser5[pd.isnull(ser5)]===========
地理 NaN
dtype: float64
==============pd.notnull(ser5)================
地理 False
语文 True
历史 True
数学 True
dtype: bool
==============ser5[pd.notnull(ser5)]==========
语文 90.0
历史 98.0
数学 99.0
dtype: float64
Series自动对齐
当多个series对象之间进行运算的时候,如果不同series之间具有不同的索引值,那么运算会自动对齐不同索引值的数据,如果某个series没有某个索引值,那么最终结果会赋值为NaN。
ser6=pd.Series(data=[99,98,97],index=['语文','数学','历史'])
ser7=pd.Series(data=[99,98,97,100],index=['语文','数学','历史','文言文'])
print('==============ser6+ser7================')
print(ser6+ser7)
print('==============ser6-ser7================')
print(ser6-ser7)
print('==============ser6*ser7================')
print(ser6*ser7)
print('==============ser6/ser7================')
print(ser6/ser7)
print('==============ser6**ser7================')
print(ser6**ser7)
==============ser6+ser7================
历史 194.0
数学 196.0
文言文 NaN
语文 198.0
dtype: float64
==============ser6+ser7================
历史 0.0
数学 0.0
文言文 NaN
语文 0.0
dtype: float64
==============ser6+ser7================
历史 9409.0
数学 9604.0
文言文 NaN
语文 9801.0
dtype: float64
==============ser6+ser7================
历史 1.0
数学 1.0
文言文 NaN
语文 1.0
dtype: float64
==============ser6+ser7================
历史 5.210246e+192
数学 1.380878e+195
文言文 NaN
语文 3.697296e+197
dtype: float64
Series及其索引的name属性
Series对象本身以及索引都具有一个name属性,默认为空,根据需要可以进行赋值操作
ser8=pd.Series(data=[99,98,97],index=['Dov','Drld','Heil'])
ser8.name='语文'
ser8.index.name='考试成绩' # 像不像索引的列名
print(ser8)
考试成绩
Dov 99
Drld 98
Heil 97
Name: 语文, dtype: int64
三、DataFrame
创建
DateFrame 在python的中type()为 <class 'pandas.core.frame.DataFrame'>
DateFrame的创建主要有三种方式:
1)通过二维数组创建数据框
arr2 = np.array(np.arange(16)).reshape(4,4)
df1 = pd.DataFrame(arr2)0 1 2 3
0 0 1 2 3
1 4 5 6 7
2 8 9 10 11
3 12 13 14 15
从这个输出我们可以看到,默认的索引和列名都是[0, N-1]的形式。我们可以在创建DataFrame的时候指定列名和索引,像这样:
df2 = pd.DataFrame(np.arange(16).reshape(4,4),columns=["column1", "column2", "column3", "column4"],index=["a", "b", "c", "d"])
print("df2:\n{}\n".format(df2))
# 结果如下column1 column2 column3 column4
a 0 1 2 3
b 4 5 6 7
c 8 9 10 11
d 12 13 14 15
请注意:DataFrame的不同列可以是不同的数据类型。如果以Series数组来创建DataFrame,每个Series将成为一行,而不是一列,例如:
noteSeries = pd.Series(["C", "D", "E", "F", "G", "A", "B"],index=[1, 2, 3, 4, 5, 6, 7])
weekdaySeries = pd.Series(["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],index=[1, 2, 3, 4, 5, 6, 7])
df4 = pd.DataFrame([noteSeries, weekdaySeries])
print("df4:\n{}\n".format(df4))
# df4的输出如下:1 2 3 4 5 6 7
0 C D E F G A B
1 Mon Tue Wed Thu Fri Sat Sun
2)通过字典的方式创建数据框
以下以两种字典来创建数据框,一个是字典列表,一个是嵌套字典。
dic2 = {'a':[1,2,3,4],'b':[5,6,7,8],'c':[9,10,11,12],'d':[13,14,15,16]}
df2 = pd.DataFrame(dic2)
dic3 = {'one':{'a':1,'b':2,'c':3,'d':4},'two':{'a':5,'b':6,'c':7,'d':8},'three':{'a':9,'b':10,'c':11,'d':12}}
df3 = pd.DataFrame(dic3)# 结果如下:a b c d
0 1 5 9 13
1 2 6 10 14
2 3 7 11 15
3 4 8 12 16one two three
a 1 5 9
b 2 6 10
c 3 7 11
d 4 8 12
字典的“键”("name","marks","price")就是 DataFrame 的 columns 的值(名称),字典中每个“键”的“值”是一个列表,它们就是那一竖列中的具体填充数据。
上面的dic2定义中没有确定索引,所以,按照惯例(Series 中已经形成的惯例)就是从 0 开始的整数。从上面的结果中很明显表示出来,这就是一个二维的数据结构(类似 excel 或者 mysql 中的查看效果)。
上面的数据显示中,columns 的顺序没有规定,就如同字典中键的顺序一样,但是在 DataFrame 中,columns 跟字典键相比,有一个明显不同,就是其顺序可以被规定,比如:
dic2_1 = DataFrame(dic2,columns=['b','a','c','d'])
Index对象
通过索引值或索引标签获取数据
pandas的Index对象包含了描述轴的元数据信息。当创建Series或者DataFrame的时候,标签的数组或者序列会被转换成Index。可以通过下面的方式获取到DataFrame的列和行的Index对象:
dic3 = {'one':{'a':1,'b':2,'c':3,'d':4},'two':{'a':5,'b':6,'c':7,'d':8},'three':{'a':9,'b':10,'c':11,'d':12}}
df3 = pd.DataFrame(dic3)
print(df3.columns) # 输出:Index(['one', 'two', 'three'], dtype='object')
print(df3.index) # 输出:Index(['a', 'b', 'c', 'd'], dtype='object')
Index并非集合,因此其中可以包含重复的数据
Index对象的值是不可以改变,因此可以通过它安全的访问数据
DataFrame提供了下面两个操作符来访问其中的数据:
print(df3[['one','two']]) # df3[列索引]
print(df3.loc[['a','b'], ['one','two']]) # loc[行索引,列索引]
print(df3.iloc[[0, 1], 0]) # iloc[行下标,列下标]# 第二行代码访问了行索引为a和b,列索引为'one','two'的元素。第三行代码访问了行下标为0和1(对于df3来说,行索引和行下标刚好是一样的,所以这里都是0和1,但它们却是不同的含义),列下标为0的元素。one two
a 1 5
b 2 6
c 3 7
d 4 8one two
a 1 5
b 2 6a 1
b 2
Name: one, dtype: int64
自动化对齐
如果有两个序列,需要对这两个序列进行算术运算,这时索引的存在就体现的它的价值了—自动化对齐.
s5 = pd.Series(np.array([10,15,20,30,55,80]),index = ['a','b','c','d','e','f'])
s6 = pd.Series(np.array([12,11,13,15,14,16]),index = ['a','c','g','b','d','f'])
s5 + s6
s5/s6
# 结果如下
a 22.0
b 30.0
c 31.0
d 44.0
e NaN
f 96.0
g NaN
dtype: float64a 0.833333
b 1.000000
c 1.818182
d 2.142857
e NaN
f 5.000000
g NaN
dtype: float64
由于s5中没有对应的g索引,s6中没有对应的e索引,所以数据的运算会产生两个缺失值NaN。注意,这里的算术结果就实现了两个序列索引的自动对齐,而非简单的将两个序列加总或相除。对于数据框的对齐,不仅仅是行索引的自动对齐,同时也会自动对齐列索引(变量名)
DataFrame中同样有索引,而且DataFrame是二维数组的推广,所以其不仅有行索引,而且还存在列索引,关于数据框中的索引相比于序列的应用要强大的多,这部分内容将放在数据查询中讲解。
四、文件操作
文件读取
pandas库提供了一系列的read_函数来读取各种格式的文件,它们如下所示:
- read_csv
- read_table
- read_fwf
- read_clipboard
- read_excel
- read_hdf
- read_html
- read_json
- read_msgpack
- read_pickle
- read_sas
- read_sql
- read_stata
- read_feather
接下来我们看一个读取Excel的简单的例子:
import pandas as pd
import numpy as np
df1 = pd.read_excel("data/test.xlsx")
print("df1:\n{}\n".format(df1))
# 这个Excel的内容如下:
df1:
C Mon
0 D Tue
1 E Wed
2 F Thu
3 G Fri
...
我们再来看读取CSV文件的例子,
df2 = pd.read_csv("data/test1.csv")
print("df2:\n{}\n".format(df2))
# 结果如下
df2:
C,Mon
D,Tue
E,Wed
F,Thu
...
如果分隔符不是,我们可以通过指定分隔符的方式来读取这个文件,像这样:
df3 = pd.read_csv("data/test2.csv", sep="|")
read_csv
支持非常多的参数用来调整读取的参数,如下表所示:
参数 | 说明 |
---|---|
path | 文件路径 |
sep或者delimiter | 字段分隔符 |
header | 列名的行数,默认是0(第一行) |
index_col | 列号或名称用作结果中的行索引 |
names | 结果的列名称列表 |
skiprows | 从起始位置跳过的行数 |
na_values | 代替NA 的值序列 |
comment | 以行结尾分隔注释的字符 |
parse_dates | 尝试将数据解析为datetime 。默认为False |
keep_date_col | 如果将列连接到解析日期,保留连接的列。默认为False 。 |
converters | 列的转换器 |
dayfirst | 当解析可以造成歧义的日期时,以内部形式存储。默认为False |
data_parser | 用来解析日期的函数 |
nrows | 从文件开始读取的行数 |
iterator | 返回一个TextParser对象,用于读取部分内容 |
chunksize | 指定读取块的大小 |
skip_footer | 文件末尾需要忽略的行数 |
verbose | 输出各种解析输出的信息 |
encoding | 文件编码 |
squeeze | 如果解析的数据只包含一列,则返回一个Series |
thousands | 千数量的分隔符 |
详细的read_csv函数说明请参见这里:pandas.read_csv
注:UTF-8以字节为编码单元,它的字节顺序在所有系统中都是一様的,没有字节序的问题,也因此它实际上并不需要BOM(“ByteOrder Mark”)。但是UTF-8 with BOM即utf-8-sig需要提供BOM。简单的说,utf-8-sig是对字节编码有序的。
这种情况发生在pandas在read csv的时候,如果报错,
key error, File "pandas/index.pyx", line 137, in pandas.index.IndexEngine.get_loc (pandas/index.c:4154)
File "pandas/index.pyx", line 159, in pandas.index.IndexEngine.get_loc (pandas/index.c:4018)
File "pandas/hashtable.pyx", line 675, in pandas.hashtable.PyObjectHashTable.get_item (pandas/hashtable.c:12368)
File "pandas/hashtable.pyx", line 683, in pandas.hashtable.PyObjectHashTable.get_item (pandas/hashtable.c:12322)
这种情况要考虑使用utf-8-sig这种编码,即encdoinf='utf-8-sig'遇到中文乱码的时候也可以试试改成这个编码
数据库数据读取
read_sql_query(sql, con, index_col=None, coerce_float=True, params=None, parse_dates=None, chunksize=None)
- sql:表示抽取数据的SQL语句,例如'select * from 表名'
- con:表示数据库连接的名称
- index_col:表示作为索引的列,默认为0-行数的等差数列
read_sql_table(table_name, con, schema=None, index_col=None, coerce_float=True, parse_dates=None, columns=None, chunksize=None)
- table_name:表示抽取数据的表名
- con:表示数据库连接的名称
- index_col:表示作为索引的列,默认为0-行数的等差数列
- columns:数据库数据读取后的列名。
read_sql(sql, con, index_col=None, coerce_float=True, params=None, parse_dates=None, columns=None, chunksize=None)
- sql:表示抽取数据的表名或者抽取数据的SQL语句,例如'select * from 表名'
- con:表示数据库连接的名称
- index_col:表示作为索引的列,默认为0-行数的等差数列
- columns:数据库数据读取后的列名。
建议:用前两个
# 读取数据库
from sqlalchemy import create_engine
conn = create_engine('mysql+pymysql://root:root@127.0.0.1/test?charset=utf8', encoding='utf-8', echo=True)
# data1 = pd.read_sql_query('select * from data', con=conn)
# print(data1.head())data2 = pd.read_sql_table('data', con=conn)
print(data2.tail())
print(data2['X'][1])
数据库连接字符串各参数说明
'mysql+pymysql://root:root@127.0.0.1/test?charset=utf8'
连接器://用户名:密码@数据库所在IP/访问的数据库名称?字符集
将数据写出为csv
DataFrame.to_csv(path_or_buf=None, sep=',', na_rep='', float_format=None, columns=None, header=True, index=True, index_label=None, mode='w', encoding=None, compression=None, quoting=None, quotechar='"', line_terminator='\n', chunksize=None, tupleize_cols=False, date_format=None, doublequote=True, escapechar=None, decimal='.')
- path_or_buf:数据存储路径,含文件全名例如'./data.csv'
- sep:表示数据存储时使用的分隔符
- header:是否导出列名,True导出,False不导出
- index: 是否导出索引,True导出,False不导出
- mode:数据导出模式,'w'为写
- encoding:数据导出的编码
import pandas as pd
data.to_csv('data.csv',index = False)
将数据写入数据库
DataFrame.to_sql(name, con, flavor=None, schema=None, if_exists='fail', index=True, index_label=None, chunksize=None, dtype=None)
- name:数据存储表名
- con:表示数据连接
- if_exists:判断是否已经存在该表,'fail'表示存在就报错;'replace'表示存在就覆盖;'append'表示在尾部追加
- index: 是否导出索引,True导出,False不导出
from sqlalchemy import create_engine
conn =create_engine('mysql+pymysql://root:root@127.0.0.1/data?charset=utf8', encoding='utf-8', echo=True)
data.to_sql('data',con = conn)
五、查询数据
data.shape # 查看数据的形状
data.columns # 查看所有的列名
data.index # 查看索引
data.dtypes # 查看每一列数据的类型
data.ndim # 查看数据的维度
# 查询前几行 或 后几行
data.head(5)
data.tail(5)# 注意当我们提取了一列,Pandas将返回一个series,而不是一个数组
data['X'] # 取出单独某一列
data[['X','Y']] # 取出多列,如果多个列的话,必须使用双重中括号
data['X'][1] # 取出某列的某一行
data['X'][:10] # 取出某列的某几行
data[['X','Y']][:10] # 取出某几列的某几行# loc方法索引'''DataFrame.loc[行名,列名]'''
data.loc[1,['X','月份']] # 取出某几列的某一行
data.loc[1:5,['X','月份']] # 取出某几列的某几行(连续)
data.loc[[1,3,5],['X','月份']] # 取出某几列的某几行
data.loc[range(0,21,2),['X','FFMC','DC']] # 取出 x ,FFMC ,DC的0-20行所有索引名称为偶数的数据# iloc方法索引'''DataFrame.iloc[行位置,列位置]'''
data.iloc[1,[1,4]] # 取出某几列的某一行
data.iloc[0:21:2,0:data.shape[1]:2] # 取出列位置为偶数,行位置为0-20的偶数的数据# ix方法索引'''DataFrame.ix[行位置/行名,列位置/列名]'''
# 取出某几列的某一行
data.ix[1:4,[1,4]]
data.ix[1:4,1:4]
loc,iloc,ix的区别
- loc使用名称索引,闭区间
- iloc使用位置索引,前闭后开区间
- ix使用名称或位置索引,且优先识别名称,其区间根据名称/位置来改变。不建议使用ix,容易发生混淆的情况,并且运行效率低于loc和iloc,pandas考虑在后期会移除这一索引方法
通过布尔索引来实现特定信息的查询
student[student['sex'] == F] # 查询所有性别为女生的信息
student[(student['sex'] == F) & (stuent['age'] > 18)] # 多条件查询,查询所有性别为女且年龄大于18岁的信息
student[(student['sex'] == F) & (stuent['age'] > 18)] [['name' , 'height']] # 查询性别为女,年龄大于18的学生的姓名 和 体重
六、统计分析
pandas模块为我们提供了非常多的描述性统计分析的指标函数
对于DataFrame,默认统计的是列的数据,如果想要统计行的,需要加axis=1
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.randint(1,100,size = 100)d1.count() # 非空元素计算
d1.min() # 最小值
d1.max() # 最大值
d1.idxmin() # 最小值的位置,类似于R中的which.min函数
d1.idxmax() # 最大值的位置,类似于R中的which.max函数
d1.quantile(0.1) # 10%分位数
d1.sum() # 求和
d1.mean() # 均值
d1.median()# 中位数
d1.mode() # 众数
d1.var() # 方差
d1.std() # 标准差
d1.mad() # 平均绝对偏差
d1.skew() # 偏度
d1.kurt() # 峰度d1.sum() # 求和,默认列
d1.sum(axis=1) # 求和,行
上述方法一维和二维均可用。
# 一次性输出多个描述性统计指标,descirbe方法只能针对序列或数据框,一维数组是没有这个方法的
d1.describe()
# student['Sex'].describe()
'''
count:非空值的数目
mean:数值型数据的均值
std:数值型数据的标准差
min:数值型数据的最小值
25%:数值型数据的下四分位数
50%:数值型数据的中位数
75%:数值型数据的上四分位数
max:数值型数据的最大值
''
相关系数(Correlation coefficient):反映两个样本/样本之间的相互关系以及之间的相关程度。在COV的基础上进行了无量纲化操作,也就是进行了标准化操作
协方差(Covariance, COV):反映两个样本/变量之间的相互关系以及之间的相关程度。
df.corr() # 相关系数
df.cov() # 协方差
df.corr('spearman') # 相关系数的计算可以调用pearson方法或kendell方法或spearman方法,默认使用pearson方法
df.corrwith(df['x1']) # 如果只想关注某一个变量与其余变量的相关系数的话,可以使用corrwith,如下方只关心x1与其余变量的相关系数
转置
df3.T
对轴进行排序
a.sort_index(axis=1,ascending=False);
# 其中axis=1表示对所有的columns进行排序,下面的数也跟着发生移动。后面的ascending=False表示按降序排列,参数缺失时默认升序。
对DataFrame中的值排序
a.sort(columns='x') # 即对a中的x这一列,从小到大进行排序。注意仅仅是x这一列,而上面的按轴进行排序时会对所有的columns进行操作。
unique方法用于获取Series中的唯一值数组(去重数据后的数组)
value_counts方法用于计算一个Series中各值的出现频率
isin方法用于判断矢量化集合的成员资格,可用于选取Series中或者DataFrame中列中数据的子集
# unique() 对于dataframe必须要指定是哪一列,对于series可以直接使用unique
df7["数学"].unique()
array([78, 89, 90], dtype=int64)# value_counts()对于dataframe必须要指定是哪一列,对于series可以直接使用value_counts
df7["数学"].value_counts()
89 2
78 1
90 1
Name: 数学, dtype: int64
mask=[89,90]print(df7.isin(mask))
print("========================================")
print(df7[df7.isin(mask)])age 历史 数学 语文
one False True False False
two False False True False
three False False True False
four False False True True
========================================age 历史 数学 语文
one NaN 90.0 NaN NaN
two NaN NaN 89.0 NaN
three NaN NaN 89.0 NaN
four NaN NaN 90.0 90.0
七、类似于SQL的操作
增:
添加新行或增加新列.可以通过concat函数实现 pd.contat([student,student2])
在数据库中union必须要求两张表的列顺序一致,而这里concat函数可以自动对齐两个数据框的变量!
对于新增的列没有赋值,就会出现空NaN的形式。
其他方式
In [105]: data['new'] = 'token' # 增加列
In [106]: data
Out[106]:name price new
0 BTC 50000 token
1 ETH 4000 token
2 EOS 150 tokenIn [109]: data.loc['3'] = ['ae',200,'token'] # 增加行
In [110]: data
Out[110]:name price type
0 BTC 50000 token
1 ETH 4000 token
2 EOS 150 token
3 ae 200 token
删
# 使用drop()。该方法返回的是Copy而不是视图,要想真正在原数据里删除行,设置inplace=True;
# axis:0,表示删除行;1,表示删除列。
data.drop('列',axis=1,inplace=True)
data.drop('行',axis=0,inplace=True)# del
del data # 删除对象,该命令可以删除Python的所有对象
del data['type'] # 删除列
改:
结合布尔索引直接赋值即可
分组聚合:groupby()函数
# 分组
group1 = data.groupby('性别')
group2 = data.groupby(['入职时间','性别'])# 查看有多少组
group1.size()
用groupby方法分组后的结果并不能直接查看,而是被存在内存中,输出的是内存地址。实际上分组后的数据对 象GroupBy类似Series与DataFrame,是pandas提供的一种对象。
Groupby对象常见方法
Grouped对象的agg方法
Grouped.agg(函数或包含了字段名和函数的字典)
# 第一种情况
group[['年龄','工资']].agg(min)# 对不同的列进行不同的聚合操作
group.agg({'年龄':max,'工资':sum})# 上述过程中使用的函数均为系统math库所带的函数,若需要使用pandas的函数则需要做如下操作
group.agg({'年龄':lambda x:x.max(),'工资':lambda x:x.sum()})
根据性别分组,计算各组别中学生身高和体重的平均值:
如果不对原始数据作限制的话,聚合函数会自动选择数值型数据进行聚合计算。如果不想对年龄计算平均值的话,就需要剔除改变量:
groupby还可以使用多个分组变量,例如根本年龄和性别分组,计算身高与体重的平均值:
还可以对每个分组计算多个统计量:
排序:
我们可以使用order、sort_index和sort_values实现序列和数据框的排序工作
我们再试试降序排序的设置:
上面两个结果其实都是按值排序,并且结果中都给出了警告信息,即建议使用sort_values()函数进行按值排序。
在数据框中一般都是按值排序,例如:
多表连接:
连接分内连接和外连接,在数据库语言中通过join关键字实现,pandas我比较建议使用merger函数实现数据的各种连接操作。
如下是构造一张学生的成绩表:
现在想把学生表student与学生成绩表score做一个关联,该如何操作呢?
默认情况下,merge函数实现的是两个表之间的内连接,即返回两张表中共同部分的数据。可以通过how参数设置连接的方式,left为左连接;right为右连接;outer为外连接。
左连接实现的是保留student表中的所有信息,同时将score表的信息与之配对,能配多少配多少,对于没有配对上的Name,将会显示成绩为NaN。
八、缺失值处理
现实生活中的数据是非常杂乱的,其中缺失值也是非常常见的,对于缺失值的存在可能会影响到后期的数据分析或挖掘工作,那么我们该如何处理这些缺失值呢?常用的有三大类方法,即删除法、填补法和插值法。
- 删除法:当数据中的某个变量大部分值都是缺失值,可以考虑删除改变量;当缺失值是随机分布的,且缺失的数量并不是很多是,也可以删除这些缺失的观测。
- 替补法:对于连续型变量,如果变量的分布近似或就是正态分布的话,可以用均值替代那些缺失值;如果变量是有偏的,可以使用中位数来代替那些缺失值;对于离散型变量,我们一般用众数去替换那些存在缺失的观测。
- 插补法:插补法是基于蒙特卡洛模拟法,结合线性模型、广义线性模型、决策树等方法计算出来的预测值替换缺失值。
方法 | 说明 |
dropna | 根据标签的值中是否存在缺失数据对轴标签进行过滤(删除), 可以通过阈值的调节对缺失值的容忍度 |
fillna | 用指定值或者插值的方式填充缺失数据,比如: ffill或者bfill |
isnull | 返回一个含有布尔值的对象,这些布尔值表示那些值是缺失值NA |
notnull | isnull的否定式 |
删除法:直接删除缺失值
默认情况下,数据中只要含有缺失值NaN,该数据行就会被删除,如果使用参数how=’all’,则表明只删除所有行为缺失值的观测。
用常数填补所有缺失值
采用前项填充或后向填充
使用常量填充不同的列
用均值或中位数填充各自的列
很显然,在使用填充法时,相对于常数填充或前项、后项填充,使用各列的众数、均值或中位数填充要更加合理一点,这也是工作中常用的一个快捷手段。
九、数据透视表
在Excel中有一个非常强大的功能就是数据透视表,通过托拉拽的方式可以迅速的查看数据的聚合情况,这里的聚合可以是计数、求和、均值、标准差等。
pandas为我们提供了非常强大的函数pivot_table(),该函数就是实现数据透视表功能的。对于上面所说的一些聚合函数,可以通过参数aggfunc设定。我们先看看这个函数的语法和参数吧:
我们仍然以student表为例,来认识一下数据透视表pivot_table函数的用法:
对一个分组变量(Sex),一个数值变量(Height)作统计汇总
对一个分组变量(Sex),两个数值变量(Height,Weight)作统计汇总
对两个分组变量(Sex,Age),两个数值变量(Height,Weight)作统计汇总
很显然这样的结果并不像Excel中预期的那样,该如何变成列联表的形式的?很简单,只需将结果进行非堆叠操作(unstack)即可:
使用多个聚合函数
有关更多数据透视表的操作,可参考《Pandas透视表(pivot_table)详解》一文,链接地址:http://python.jobbole.com/81212/
多层索引的使用
最后我们再来讲讲pandas中的一个重要功能,那就是多层索引。在序列中它可以实现在一个轴上拥有多个索引,就类似于Excel中常见的这种形式:
对于这样的数据格式有什么好处呢?pandas可以帮我们实现用低维度形式处理高维数数据,这里举个例子也许你就能明白了:
对于这种多层次索引的序列,取数据就显得非常简单了:
对于这种多层次索引的序列,我们还可以非常方便的将其转换为数据框的形式:
以上针对的是序列的多层次索引,数据框也同样有多层次的索引,而且每条轴上都可以有这样的索引,就类似于Excel中常见的这种形式:
我们不妨构造一个类似的高维数据框:
同样,数据框中的多层索引也可以非常便捷的取出大块数据:
在数据框中使用多层索引,可以将整个数据集控制在二维表结构中,这对于数据重塑和基于分组的操作(如数据透视表的生成)比较有帮助。
就拿student二维数据框为例,我们构造一个多层索引数据集:
http://www.cnblogs.com/nxld/p/6058591.html
https://www.cnblogs.com/lingLongBaby/p/7147378.html
http://www.cnblogs.com/WoLykos/p/9349581.html
https://www.cnblogs.com/zuizui1204/p/6423069.html