整理自Welcome to Python For Data Analysis’s documentation!。
预备知识:python基础,线性代数(矩阵运算)基础概念
pandas数据结构
- Series
- DataFrame
- Index数据类型
重要的功能
- 重新索引
- 从一个坐标轴删除条目
- 索引,挑选和过滤
- 算术和数据对齐、填充
首先用pip安装pandas包,并导入
from pandas import Series, DataFrame
import pandas as pd
import numpy as np
print(pd.__version__)
有两个重要的数据结构: Series 和 DataFrame
pandas数据结构
Series
Series包括index和value,和dict很像,也可以看成一个定长的、有序的词典
- 构造
obj = Series([4, 7, -5, 3]) # 自动添加index
obj2 = Series([4, 7, -5, 3], index=['d', 'b', 'a', 'c']) # 指定index
sdata = {'Ohio': 35000, 'Texas': 71000, 'Oregon': 16000, 'Utah': 5000}
obj3 = Series(sdata) # 从字典创建Series,索引会排序
states = ['California', 'Ohio', 'Oregon', 'Texas']
obj4 = Series(sdata, index=states) # 也可以指定索引顺序,但可能有值缺失
检测缺失值:obj4.isnull()
从索引数据访问:obj2[‘a’]
对于Series的value可以直接进行过滤和Numpy的数学操作,就像数组一样
print(obj2[obj2 > 0])
print(obj2 * 2)
print(np.exp(obj2))
数据对齐:执行不同Series之间的运算时,将按索引值对齐后运算。比如执行
obj3+obj4
name:Series对象本身和它的index都有一个name属性,它和pandas的其它一些关键功能整合在一起:
obj4.name = 'population'
obj4.index.name = 'state'
print(obj4) # 打印试试看
- 修改索引:对obj.index重新赋值(dict型)即可
DataFrame
一个Datarame表示一个表格,类似电子表格的数据结构,包含一个经过排序的列表集,它们每一个都可以有不同的类型值(数字,字符串,布尔等等)。
Datarame有行和列的索引;它可以被看作是一个Series的字典(每个Series共享一个索引)。在DataFrame里的面向行和面向列的操作大致是对称的。
在底层,数据是作为一个或多个二维数组存储的,而不是列表,字典,或其它一维的数组集合。
- 构造:用字典构造,字典的key为列的值,values是等长的列表。
data = {'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada'],
'year': [2000, 2001, 2002, 2001, 2002],
'pop': [1.5, 1.7, 3.6, 2.4, 2.9]}
frame = DataFrame(data) # 自动生成行索引,也可以像Series一样用index指定索引
frame2 = DataFrame(data, columns=['year', 'state', 'pop', 'debt'],index=['one', 'two', 'three', 'four', 'five']) # 用index指定索引,用columns指定列的值
# 使用嵌套的字典构造,外部键会被解释为列索引,内部键会被解释为行索引:
pop = {'Nevada': {2001: 2.4, 2002: 2.9}, 'Ohio': {2000: 1.5, 2001: 1.7, 2002: 3.6}}
frame3 = DataFrame(pop) # Nevada是行索引,年份是列索引
还有更多的构造方法。
- 访问:对列进行访问,有两种方式
frame.['state'] # 字典记法
frame.state
对行进行访问,比如通过索引访问一行
frame.ix['three']
- 数值修改:一列可以通过一个整数或者一个数组赋值。且通过列表或数组给一列赋值时,所赋的值的长度必须和DataFrame的长度相匹配。
frame2.debt = 16.5
frame2.debt = np.arange(5.0)
如果你使用Series来赋值,它会代替在DataFrame中精确匹配的索引的值,并在说有的空洞插入丢失数据:
val = Series([-1.2, -1.5, -1.7], index=['two', 'four', 'five'])
frame2['debt'] = val
给一个不存在的列赋值,将会创建一个新的列。 像字典一样 del 关键字将会删除列
frame2['eastern'] = frame2.state == 'Ohio'
del frame2['eastern']
索引DataFrame时返回的Series是底层数据的一个引用,而不是一份复制的数据。因此,任何在Series上的修改都会影响原来的DataFrame。想要获得复制的数据,可以使用Series的
copy
函数来显式的拷贝。
- 属性
values:frame.values返回一个二维数组
columns
index
Index数据类型
用来保存坐标轴标签和其它元数据(如坐标轴名或名称),是不可变的
obj = Series(range(3), index=['a', 'b', 'c'])
index = obj.index # 返回一个Index类型的Numpy数组
Index类型有多种类似集合的方法,见这里;
重要的功能
重新索引
使用reindex重排索引。对于Dataframe可以对index和column都重新索引。
# 对Series重新索引
obj2 = obj.reindex(['a', 'b', 'c', 'd', 'e'])
obj.reindex(['a', 'b', 'c', 'd', 'e'], fill_value=0)
# 对index和column索引
frame.reindex(index=['a', 'b', 'c', 'd'], method='ffill', columns=states)
# 当reindex的参数只传入一个列表的时候,是对行重新索引
在索引的时候要对数据进行内插或填充,使用method
方法
obj3 = Series(['blue', 'purple', 'yellow'], index=[0, 2, 4])
obj3.reindex(range(6), method='ffill') # ffill或pad前向(或进位)填充,bfill或backfill后向(或退位)填充
# 结果为
#0 blue
#1 blue
#2 purple
#3 purple
#4 yellow
#5 yellow
也可以使用带标签索引的ix
可以把重新索引做的更简单:
frame.ix[['a', 'b', 'c', 'd'], states]
从一个坐标轴删除条目
对于Series,使用drop
,返回drop掉某些行之后的对象。不改变原来的对象。
obj = Series(np.arange(5.), index=['a', 'b', 'c', 'd', 'e'])
new_obj = obj.drop('c')
obj.drop(['d', 'c'])
对于Dataframe,
data = DataFrame(np.arange(16).reshape((4, 4)), index=['Ohio', 'Colorado', 'Utah', 'New York'], columns=['one', 'two', 'three', 'four'])
data.drop(['Colorado', 'Ohio']) # 删除行
data.drop('two', axis=1) # 删除列
索引,挑选和过滤
注:这里的索引指的是筛选
Series索引( obj[…] )的工作原理类似与NumPy索引,除了可以使用Series的索引值,也可以仅使用整数来索引。
obj = Series(np.arange(4.), index=['a', 'b', 'c', 'd'])
# 以下方法相同
obj['b']
obj[1]
标签可以切片,与正常的python切片不一样,会把结束点都包含进去。
可以对切片的部分进行赋值。因为切片出来是引用而不是复制的数据。
obj['b':'c'] = 5 # b,c行的数据都为5
DataFrame可以如上面说的按列索引,不过也可以按行索引,比如
data[:2] # 截取前两行
data[data['three'] > 5] # 后者返回一个值为bool的Series,满足的行被选择
筛选:
data < 5 # 返回值为bool类型的dataframe
data[data < 5] = 0 # 小于5的值置0
使用ix重新索引:
data.ix[['Colorado',Utah], ['two', 'three']] # 前面的参数作为行索引,后面的参数作为列名
data.ix[2] # 选择第3行作为新的Series
data.ix[:'Utah', 'two'] # 可以对行进行切片选择
data.ix[data.three > 5, :3]
obj[val] | 功能 |
---|---|
obj.ix[val] | 从DataFrame的行集选择单行 |
obj.ix[:, val] | 从列集选择单列 |
obj.ix[val1, val2] | 选择行和列 |
reindex | 转换一个或多个轴到新的索引 |
xs 方法 | 通过标签选择单行或单列到一个Series |
icol, irow 方法 | 通过整数位置,分别的选择单行或单列到一个Series |
get_value, set_value 方法 | 通过行和列标选择一个单值 |
参数内可以使用:布尔数组(过滤行),切片(行切片),或bool型的DataFrame(根据一些标准来筛选值)。
算术和数据对齐、填充
带填充值的算术方法
之前已经见过对Datafram做运算的时候会根据行和列的索引自动对齐,缺失的地方引入NA。
对于NA的填充,有如下方法:
# 构造两个DataFrame
df1 = DataFrame(np.arange(12.).reshape((3,4)),columns=list('abcd'))
df2 = DataFrame(np.arange(20.).reshape((4,5)),columns=list('abcde'))
df1.add(df2, fill_value=0) # 如果是fill_value是None,缺失值会被填充为NA,如果是0,会被填充为df2中的值
(df1+df2).fillna(0) # 缺失值置0
DataFrame 和 Series 间的操作
DataFrame和Series间的算术操作与NumPy数组类似。
按我的理解,Series相当于DataFrame的一行,也就是Series的index是DataFrame的列名。
考虑一个二维数组(Dataframe)和它的一个行(Series)间的相减:
frame = DataFrame(np.arrange(12.).reshape((4, 3)), columns = list('bde'), index = ['Utah', 'Ohio', 'Texas', 'Oregon'])
series = frame.ix[0] # 取第一行
frame - series # frame的每一行会都减去series
如果一个索引在Series的index或者DataFrame的columns中找不到,运算后相应列会被填充为NA。
上面是按行相减。如果想要让Dataframe按列与Series相减,要用到DataFrame.sub方法
series3 = frame['d']
frame.sub(series3, axis=0) # frame的每一列会都减去series。axis=0表示frame的第0行对齐series3的第一个值进行相减