一、pandas概述
pandas :pannel data analysis(面板数据分析)。pandas是基于numpy构建的,pandas是基于NumPy数组构建的,特别是基于数组的函数和不使用for循环的数据处理。为时间序列分析提供了很好的支持。pandas中有两个主要的数据结构,一个是Series,另一个是DataFrame。
import pandas as pd
from pandas import Series, DataFrame
pandas的数据结构介绍
二、数据结构 Series
Series 类似于一维数组与字典(map)数据结构的结合。它由一组数据和一组与数据相对应的数据标签(索引index)组成。这组数据和索引标签的基础都是一个一维ndarray数组。可将index索引理解为行索引。 Series的表现形式为:索引在左,数据在右。
• 获取数据和索引:ser_obj.index, ser_obj.values
• 预览数据:ser_obj.head(n), ser_obj.tail(n)
import pandas as pd
from pandas import Series,DataFrame
print '用一维数组生成Series'
x = Series([1,2,3,4])
print x
'''
0 1
1 2
2 3
3 4
'''
print x.values # [1 2 3 4]
# 默认标签为0到3的序号
print x.index # RangeIndex(start=0, stop=4, step=1)
print '指定Series的index' # 可将index理解为行索引
x = Series([1, 2, 3, 4], index = ['a', 'b', 'd', 'c'])
print x
'''
a 1
b 2
d 3
c 4
'''
print x.index # Index([u'a', u'b', u'd', u'c'], dtype='object')
print x['a'] # 通过行索引来取得元素值:1
x['d'] = 6 # 通过行索引来赋值
print x[['c', 'a', 'd']] # 类似于numpy的花式索引
'''
c 4
a 1
d 6
'''
print x[x > 2] # 类似于numpy的布尔索引
'''
d 6
c 4
'''
print 'b' in x # 类似于字典的使用:是否存在该索引:True
print 'e' in x # False
print x*2 #使用NumPy函数或类似NumPy的运算
'''
a 1
b 4
d 6
c 8
'''
print np.exp(x)
'''
a 2.718
b 7.389
c 20.085
d 54.598
'''
print '使用字典来生成Series'
data = {'a':1, 'b':2, 'd':3, 'c':4}
x = Series(data)
print x
'''
a 1
b 2
c 4
d 3
'''
print '使用字典生成Series,并指定额外的index,不匹配的索引部分数据为NaN。'
exindex = ['a', 'b', 'c', 'e']
y = Series(data, index = exindex) # 类似替换索引
print y
'''
a 1.0
b 2.0
c 4.0
e NaN
'''
print 'Series相加,相同行索引相加,不同行索引则数值为NaN'
print x+y
'''
a 2.0
b 4.0
c 8.0
d NaN
e NaN
'''
print '指定Series/索引的名字'
y.name = 'weight of letters'
y.index.name = 'letter'
print y
'''
letter
a 1.0
b 2.0
c 4.0
e NaN
Name: weight of letters, dtype: float64
'''
print '替换index'
y.index = ['a', 'b', 'c', 'f']
print y # 不匹配的索引部分数据为NaN
'''
a 1.0
b 2.0
c 4.0
f NaN
Name: weight of letters, dtype: float64
'''
三、数据结构 DataFrame
DataFrame是一个类似表格的数据结构,索引包括列索引和行索引,包含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔值等)。DataFrame的每一行和每一列都是一个Series,这个Series的name属性为当前的行索引名/列索引名。
通过列索引获取列数据(Series类型 ):df_obj[col_idx] 或 df_obj.col_idx
.ix,标签与位置混合索引
data = {'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada', 'Nevada'],
'year': [2000, 2001, 2002, 2001, 2002, 2003],
'pop': [1.5, 1.7, 3.6, 2.4, 2.9, 3.2]}
frame = pd.DataFrame(data)
print frame
'''
pop state year
0 1.5 Ohio 2000
1 1.7 Ohio 2001
2 3.6 Ohio 2002
3 2.4 Nevada 2001
4 2.9 Nevada 2002
5 3.2 Nevada 2003
'''
print frame.head()#head方法会选取前五行
'''
pop state year
0 1.5 Ohio 2000
1 1.7 Ohio 2001
2 3.6 Ohio 2002
3 2.4 Nevada 2001
4 2.9 Nevada 2002
'''
#如果指定了列序列,则DataFrame的列就会按照指定顺序进行排列:
frame = pd.DataFrame(data, columns=['year', 'state', 'pop'])
print frame
'''
year state pop
0 2000 Ohio 1.5
1 2001 Ohio 1.7
2 2002 Ohio 3.6
3 2001 Nevada 2.4
4 2002 Nevada 2.9
5 2003 Nevada 3.2
'''
#如果传入的列在数据中找不到,就会在结果中产生缺失值:
frame2 = frame2 = pd.DataFrame(data, columns=['year', 'state', 'pop', 'debt'],
index=['one', 'two', 'three', 'four','five', 'six'])
print frame2
'''
year state pop debt
one 2000 Ohio 1.5 NaN
two 2001 Ohio 1.7 NaN
three 2002 Ohio 3.6 NaN
four 2001 Nevada 2.4 NaN
five 2002 Nevada 2.9 NaN
six 2003 Nevada 3.2 NaN
'''
print frame2.columns #Index(['year', 'state', 'pop', 'debt'], dtype='object')
#通过类似字典标记的方式或属性的方式,可以将DataFrame的列获取为一个Series
print frame2['state']
'''
one Ohio
two Ohio
three Ohio
four Nevada
five Nevada
six Nevada
Name: state, dtype: object
'''
print frame2.year
'''
one 2000
two 2001
three 2002
four 2001
five 2002
six 2003
Name: year, dtype: int64
'''
#行也可以通过位置或名称的方式进行获取,比如用loc属性
print frame2.loc['three']
'''
year 2002
state Ohio
pop 3.6
debt NaN
Name: three, dtype: object
'''
#列可以通过赋值的方式进行修改。
frame2['debt'] = 16.5
print frame2
'''
year state pop debt
one 2000 Ohio 1.5 16.5
two 2001 Ohio 1.7 16.5
three 2002 Ohio 3.6 16.5
four 2001 Nevada 2.4 16.5
five 2002 Nevada 2.9 16.5
six 2003 Nevada 3.2 16.5
'''
frame2['debt'] = np.arange(6.)
print frame2
'''
year state pop debt
one 2000 Ohio 1.5 0.0
two 2001 Ohio 1.7 1.0
three 2002 Ohio 3.6 2.0
four 2001 Nevada 2.4 3.0
five 2002 Nevada 2.9 4.0
six 2003 Nevada 3.2 5.0
'''
#将列表或数组赋值给某个列时,其长度必须跟DataFrame的长度相匹配。如果赋值的是一个Series,就会精确
#匹配DataFrame的索引,所有的空位都将被填上缺失值
val = pd.Series([-1.2, -1.5, -1.7], index=['two', 'four', 'five'])
frame2['debt'] = val
print frame2
'''
year state pop debt
one 2000 Ohio 1.5 NaN
two 2001 Ohio 1.7 -1.2
three 2002 Ohio 3.6 NaN
four 2001 Nevada 2.4 -1.5
five 2002 Nevada 2.9 -1.7
six 2003 Nevada 3.2 NaN
'''
frame2['eastern'] = frame2.state == 'Ohio'
print frame2
'''
year state pop debt eastern
one 2000 Ohio 1.5 NaN True
two 2001 Ohio 1.7 -1.2 True
three 2002 Ohio 3.6 NaN True
four 2001 Nevada 2.4 -1.5 False
five 2002 Nevada 2.9 -1.7 False
six 2003 Nevada 3.2 NaN False
'''
del frame2['eastern']
print frame2.colums #Index(['year', 'state', 'pop', 'debt'], dtype='object')
#另一种常见的数据形式是嵌套字典 如果嵌套字典传给DataFrame,pandas就会被解释为:
#外层字典的键作为列,内层键则作为行索引。
pop = {'Nevada': {2001: 2.4, 2002: 2.9},'Ohio': {2000: 1.5, 2001: 1.7, 2002: 3.6}}
frame3 = pd.DataFrame(pop)
print frame3
'''
Nevada Ohio
2000 NaN 1.5
2001 2.4 1.7
2002 2.9 3.6
'''
#跟Series一样,values属性也会以二维ndarray的形式返回DataFrame中的数据
print frame3.values
'''
array([[ nan, 1.5],
[ 2.4, 1.7],
[ 2.9, 3.6]])
'''
四、索引对象
pandas的索引对象负责管理轴标签和其他元数据(比如轴名称等)。构建Series或DataFrame时,所用到的任何数组或其他序列的标签都会被转换成一个Index。
obj = pd.Series(range(3), index=['a', 'b', 'c'])
index = obj.index
print index #Index(['a', 'b', 'c'], dtype='object')
print index[1:] #Index(['b', 'c'], dtype='object')
#Index对象是不可变的,因此用户不能对其进行修改
index[1] = 'd' # TypeError
labels = pd.Index(np.arange(3))
print labels #Int64Index([0, 1, 2], dtype='int64')
obj2 = pd.Series([1.5, -2.5, 0], index=labels)
print obj2
'''
0 1.5
1 -2.5
2 0.0
dtype: float64
'''
obj2.index is labels #True
print frame3
'''
state Nevada Ohio
year
2000 NaN 1.5
2001 2.4 1.7
2002 2.9 3.6
'''
print frame3.columns #Index(['Nevada', 'Ohio'], dtype='object', name='state')
'Ohio' in frame3.columns #True
2003 in frame3.index #False
#
obj = pd.Series(range(3), index=['a', 'b', 'c'])
index = obj.index
print index #Index(['a', 'b', 'c'], dtype='object')
print index[1:] #Index(['b', 'c'], dtype='object')
#Index对象是不可变的,因此用户不能对其进行修改
index[1] = 'd' # TypeError
labels = pd.Index(np.arange(3))
print labels #Int64Index([0, 1, 2], dtype='int64')
obj2 = pd.Series([1.5, -2.5, 0], index=labels)
print obj2
'''
0 1.5
1 -2.5
2 0.0
dtype: float64
'''
obj2.index is labels #True
print frame3
'''
state Nevada Ohio
year
2000 NaN 1.5
2001 2.4 1.7
2002 2.9 3.6
'''
print frame3.columns #Index(['Nevada', 'Ohio'], dtype='object', name='state')
'Ohio' in frame3.columns #True
2003 in frame3.index #False
#
obj = pd.Series(range(3), index=['a', 'b', 'c'])
index = obj.index
print index #Index(['a', 'b', 'c'], dtype='object')
print index[1:] #Index(['b', 'c'], dtype='object')
#Index对象是不可变的,因此用户不能对其进行修改
index[1] = 'd' # TypeError
labels = pd.Index(np.arange(3))
print labels #Int64Index([0, 1, 2], dtype='int64')
obj2 = pd.Series([1.5, -2.5, 0], index=labels)
print obj2
'''
0 1.5
1 -2.5
2 0.0
dtype: float64
'''
obj2.index is labels #True
print frame3
'''
state Nevada Ohio
year
2000 NaN 1.5
2001 2.4 1.7
2002 2.9 3.6
'''
print frame3.columns #Index(['Nevada', 'Ohio'], dtype='object', name='state')
'Ohio' in frame3.columns #True
2003 in frame3.index #False
#与python的集合不同,pandas的Index可以包含重复的标签
dup_labels = pd.Index(['foo', 'foo', 'bar', 'bar'])
print dup_labels #Index(['foo', 'foo', 'bar', 'bar'], dtype='object')
五、重新索引
pandas对象的一个重要方法是reindex,其作用是创建一个新对象,它的数据符合新的索引。
obj = pd.Series([4.5, 7.2, -5.3, 3.6], index=['d', 'b', 'a', 'c'])
print obj
'''
d 4.5
b 7.2
a -5.3
c 3.6
dtype: float64
'''
#用该Series的reindex将会根据新索引进行重排。如果某个索引值当前不存在,就引入缺失值。
obj2 = obj.reindex(['a', 'b', 'c', 'd', 'e'])
print obj2
'''
a -5.3
b 7.2
c 3.6
d 4.5
e NaN
dtype: float64
'''
#对于时间序列这样的有序数据,重新索引时可能需要做一些插值处理。method选项即可达到此目的
obj3 = pd.Series(['blue', 'purple', 'yellow'], index=[0, 2, 4])
print obj3
'''
0 blue
2 purple
4 yellow
dtype: object
'''
obj3.reindex(range(6), method='ffill')
print obj3
'''
0 blue
1 blue
2 purple
3 purple
4 yellow
5 yellow
dtype: object
'''
#借助DataFrame,reindex可以修改(行)索引和列。
frame = pd.DataFrame(np.arange(9).reshape((3, 3)),
index=['a', 'c', 'd'],columns=['Ohio', 'Texas', 'California'])
print frame
'''
Ohio Texas California
a 0 1 2
c 3 4 5
d 6 7 8
'''
frame2 = frame.reindex(['a', 'b', 'c', 'd'])
print frame2
'''
Ohio Texas California
a 0.0 1.0 2.0
b NaN NaN NaN
c 3.0 4.0 5.0
d 6.0 7.0 8.0
'''
states = ['Texas', 'Utah', 'California']
frame.reindex(columns=states)
'''
Texas Utah California
a 1 NaN 2
c 4 NaN 5
d 7 NaN 8
'''
六、丢弃指定轴上的项
丢弃某条轴上的一个或多个项很简单,只要有一个索引数组或列表即可。由于需要执行一些数据整理和集合逻辑,所以drop方法返回的是一个在指定轴上删除了指定值的新对象。
obj = pd.Series(np.arange(5.), index=['a', 'b', 'c', 'd', 'e'])
print obj
'''
a 0.0
b 1.0
c 2.0
d 3.0
e 4.0
dtype: float64
'''
new_obj = obj.drop('c')
print new_obj
'''
a 0.0
b 1.0
d 3.0
e 4.0
dtype: float64
'''
obj.drop(['d', 'c'])
'''
a 0.0
b 1.0
e 4.0
dtype: float64
'''
#对于DataFrame,可以删除任意轴上的索引值。
data = pd.DataFrame(np.arange(16).reshape((4, 4)),
index=['Ohio', 'Colorado', 'Utah', 'New York'],
columns=['one', 'two', 'three', 'four'])
print data
'''
one two three four
Ohio 0 1 2 3
Colorado 4 5 6 7
Utah 8 9 10 11
New York 12 13 14 15
'''
#用标签序列调用drop会从行标签(axis 0)删除值:
data.drop(['Colorado', 'Ohio'])
print data
'''
one two three four
Utah 8 9 10 11
New York 12 13 14 15
'''
#通过传递axis=1或axis='columns'可以删除列的值:
data.drop('two', axis=1)
print data
'''
one three four
Ohio 0 2 3
Colorado 4 6 7
Utah 8 10 11
New York 12 14 15
'''
data.drop(['two', 'four'], axis='columns')
print data
'''
one three
Ohio 0 2
Colorado 4 6
Utah 8 10
New York 12 14
'''
七、索引、选取和过滤
obj = pd.Series(np.arange(4.), index=['a', 'b', 'c', 'd'])
print obj
'''
a 0.0
b 1.0
c 2.0
d 3.0
dtype: float64
'''
print obj['b'] #1.0
print obj[1] #1.0
print obj[2:4]
'''
c 2.0
d 3.0
dtype: float64
'''
print obj[['b', 'a', 'd']]
'''
b 1.0
a 0.0
d 3.0
dtype: float64
'''
print obj[[1, 3]]
'''
b 1.0
d 3.0
dtype: float64
'''
#利用标签的切片运算与普通的Python切片运算不同,其末端是包含的:
print obj['b':'c']
'''
b 1.0
c 2.0
dtype: float64
'''
#用一个值或序列对DataFrame进行索引其实就是获取一个或多个列:
data = pd.DataFrame(np.arange(16).reshape((4, 4)),
index=['Ohio', 'Colorado', 'Utah', 'New York'],
columns=['one', 'two', 'three', 'four'])
print data
'''
one two three four
Ohio 0 1 2 3
Colorado 4 5 6 7
Utah 8 9 10 11
New York 12 13 14 15
'''
print data['two']
'''
Ohio 1
Colorado 5
Utah 9
New York 13
Name: two, dtype: int64
'''
print data[data['three'] > 5]
'''
one two three four
Colorado 4 5 6 7
Utah 8 9 10 11
New York 12 13 14 15
'''
print data < 5
'''
one two three four
Ohio True True True True
Colorado True False False False
Utah False False False False
New York False False False False
'''
print data[data < 5] = 0
'''
one two three four
Ohio 0 0 0 0
Colorado 0 5 6 7
Utah 8 9 10 11
New York 12 13 14 15
'''
八、用loc和iloc进行选取
对于DataFrame的行的标签索引,我引入了特殊的标签运算符loc和iloc。它们可以让你用类似NumPy的标记,使用轴标签(loc)或整数索引(iloc),从DataFrame选择行和列的子集。
print data.loc['Colorado', ['two', 'three']]
'''
two 5
three 6
Name: Colorado, dtype: int64
'''
#用iloc和整数进行选取
print data.iloc[2]
'''
one 8
two 9
three 10
four 11
Name: Utah, dtype: int64
'''
print data.iloc[[1, 2], [3, 0, 1]]
'''
four one two
Colorado 7 0 5
Utah 11 8 9
'''
九、算术运算和数据对齐
pandas最重要的一个功能是,它可以对不同索引的对象进行算术运算。在将对象相加时,如果存在不同的索引对,则结果的索引就是该索引对的并集。对于有数据库经验的用户,这就像在索引标签上进行自动外连接。
s1 = pd.Series([7.3, -2.5, 3.4, 1.5], index=['a', 'c', 'd', 'e'])
s2 = pd.Series([-2.1, 3.6, -1.5, 4, 3.1],index=['a', 'c', 'e', 'f', 'g'])
#自动的数据对齐操作在不重叠的索引处引入了NA值。缺失值会在算术运算过程中传播。
print s1 + s2
'''
a 5.2
c 1.1
d NaN
e 0.0
f NaN
g NaN
dtype: float64
'''
df1 = pd.DataFrame(np.arange(9.).reshape((3, 3)), columns=list('bcd'),
index=['Ohio', 'Texas', 'Colorado'])
Idf2 = pd.DataFrame(np.arange(12.).reshape((4, 3)), columns=list('bde'),
index=['Utah', 'Ohio', 'Texas', 'Oregon'])
print df1 + df2 #因为'c'和'e'列均不在两个DataFrame对象中,在结果中以缺省值呈现。行也是同样。
'''
b c d e
Colorado NaN NaN NaN NaN
Ohio 3.0 NaN 6.0 NaN
Oregon NaN NaN NaN NaN
Texas 9.0 NaN 12.0 NaN
Utah NaN NaN NaN NaN
'''
十、在算术方法中填充值
在对不同索引的对象进行算术运算时,你可能希望当一个对象中某个轴标签在另一个对象中找不到时填充一个特殊值(比如0)。
df1 = pd.DataFrame(np.arange(12.).reshape((3, 4)),columns=list('abcd'))
df2 = pd.DataFrame(np.arange(20.).reshape((4, 5)),columns=list('abcde'))
df2.loc[1, 'b'] = np.nan
print df2
'''
a b c d e
0 0.0 1.0 2.0 3.0 4.0
1 5.0 NaN 7.0 8.0 9.0
2 10.0 11.0 12.0 13.0 14.0
3 15.0 16.0 17.0 18.0 19.0
'''
print df1 + df2 #将它们相加时,没有重叠的位置就会产生NA值
'''
a b c d e
0 0.0 2.0 4.0 6.0 NaN
1 9.0 NaN 13.0 15.0 NaN
2 18.0 20.0 22.0 24.0 NaN
3 NaN NaN NaN NaN NaN
'''
print df1.add(df2, fill_value=0) #使用df1的add方法,传入df2以及一个fill_value参数
'''
a b c d e
0 0.0 2.0 4.0 6.0 4.0
1 9.0 5.0 13.0 15.0 9.0
2 18.0 20.0 22.0 24.0 14.0
3 15.0 16.0 17.0 18.0 19.0
'''
十一、DataFrame和Series之间的运算
跟不同维度的NumPy数组一样,DataFrame和Series之间算术运算也是有明确规定的。
frame = pd.DataFrame(np.arange(12.).reshape((4, 3)),
columns=list('bde'),
index=['Utah', 'Ohio', 'Texas', 'Oregon'])
series = frame.iloc[0]
print frame - series
'''
b d e
Utah 0.0 0.0 0.0
Ohio 3.0 3.0 3.0
Texas 6.0 6.0 6.0
Oregon 9.0 9.0 9.0
'''
#如果某个索引值在DataFrame的列或Series的索引中找不到,则参与运算的两个对象就会被重新索引以形成并集
series2 = pd.Series(range(3), index=['b', 'e', 'f'])
print frame + series2
'''
b d e f
Utah 0.0 NaN 3.0 NaN
Ohio 3.0 NaN 6.0 NaN
Texas 6.0 NaN 9.0 NaN
Oregon 9.0 NaN 12.0 NaN
'''
#如果你希望匹配行且在列上广播,则必须使用算术运算方法。
series3 = frame['d']
print frame.sub(series3, axis='index')
'''
b d e
Utah -1.0 0.0 1.0
Ohio -1.0 0.0 1.0
Texas -1.0 0.0 1.0
Oregon -1.0 0.0 1.0
'''
#传入的轴号就是希望匹配的轴。在本例中,我们的目的是匹配DataFrame的行索引(axis='index' or axis=0)并进行广播。
十二、函数应用和映射
NumPy的ufuncs(元素级数组方法)也可用于操作pandas对象。
frame = pd.DataFrame(np.random.randn(4, 3), columns=list('bde'),
index=['Utah', 'Ohio', 'Texas', 'Oregon'])
print frame
'''
b d e
Utah -0.204708 0.478943 -0.519439
Ohio -0.555730 1.965781 1.393406
Texas 0.092908 0.281746 0.769023
Oregon 1.246435 1.007189 -1.296221
'''
print np.abs(frame)
'''
b d e
Utah 0.204708 0.478943 0.519439
Ohio 0.555730 1.965781 1.393406
Texas 0.092908 0.281746 0.769023
Oregon 1.246435 1.007189 1.296221
'''
#另一个常见的操作是,将函数应用到由各列或行所形成的一维数组上。DataFrame的apply方法即可实现此功能.
f = lambda x: x.max() - x.min()
print frame.apply(f)#这里的函数f,计算了一个Series的最大值和最小值的差,
#在frame的每列都执行了一次。结果是一个Series,使用frame的列作为索引
'''
b 1.802165
d 1.684034
e 2.689627
dtype: float64
'''
#如果传递axis='columns'到apply,这个函数会在每行执行.
frame.apply(f, axis='columns')
'''
Utah 0.998382
Ohio 2.521511
Texas 0.676115
Oregon 2.542656
dtype: float64
'''
十三、排序和排名
根据条件对数据集排序(sorting)也是一种重要的内置运算。要对行或列索引进行排序(按字典顺序),可使用sort_index方法,它将返回一个已排序的新对象。
obj = pd.Series(range(4), index=['d', 'a', 'b', 'c'])
print obj.sort_index()
'''
a 1
b 2
c 3
d 0
dtype: int64
'''
frame = pd.DataFrame(np.arange(8).reshape((2, 4)),
index=['three', 'one'],
columns=['d', 'a', 'b', 'c'])
print frame.sort_index()
'''
d a b c
one 4 5 6 7
three 0 1 2 3
'''
print frame.sort_index(axis=1)
'''
a b c d
three 1 2 3 0
one 5 6 7 4
'''
#若要按值对Series进行排序,可使用其sort_values方法。
obj = pd.Series([4, 7, -3, 2])
print obj
'''
2 -3
3 2
0 4
1 7
dtype: int64
'''
#在排序时,任何缺失值默认都会被放到Series的末尾。
print obj.sort_values()
'''
4 -3.0
5 2.0
0 4.0
2 7.0
1 NaN
3 NaN
dtype: float64
'''
#排序一个DataFrame时,你可能希望根据一个或多个列中的值进行排序。
#将一个或多个列的名字传递给sort_values的by选项即可达到该目的
frame = pd.DataFrame({'b': [4, 7, -3, 2], 'a': [0, 1, 0, 1]})
print frame
'''
a b
0 0 4
1 1 7
2 0 -3
3 1 2
'''
print frame.sort_values(by='b')
'''
a b
2 0 -3
3 1 2
0 0 4
1 1 7
'''
十四、汇总和计算描述统计
pandas对象拥有一组常用的数学和统计方法。它们大部分都属于约简和汇总统计,用于从Series中提取单个值(如sum或mean)或从DataFrame的行或列中提取一个Series。跟对应的NumPy数组方法相比,它们都是基于没有缺失数据的假设而构建的。
df = pd.DataFrame([[1.4, np.nan], [7.1, -4.5],
[np.nan, np.nan], [0.75, -1.3]],
index=['a', 'b', 'c', 'd'],
columns=['one', 'two'])
print df
'''
one two
a 1.40 NaN
b 7.10 -4.5
c NaN NaN
d 0.75 -1.3
'''
print df.sum()
'''
one 9.25
two -5.80
dtype: float64
'''
#传入axis='columns'或axis=1将会按行进行求和运算
print df.sum(axis=1)
'''
a 1.40
b 2.60
c NaN
d -0.55
'''
#NA值会自动被排除,除非整个切片(这里指的是行或列)都是NA。通过skipna选项可以禁用该功能:
print df.mean(axis='columns', skipna=False)
'''
a NaN
b 1.300
c NaN
d -0.275
dtype: float64
'''
数据加载、存储与文件格式
十五、读写文本格式的数据
pandas提供了一些用于将表格型数据读取为DataFrame对象的函数。这边我将只介绍读取csv文件。
!cat examples/ex1.csv #cat命令 查看csv文件内容
a,b,c,d,message
1,2,3,4,hello
5,6,7,8,world
9,10,11,12,foo
#read_csv
df = pd.read_csv('examples/ex1.csv')
print df
'''
a b c d message
0 1 2 3 4 hello
1 5 6 7 8 world
2 9 10 11 12 foo
'''
#read_table
df1 = pd.read_table('examples/ex1.csv', sep=',')
print df1
'''
a b c d message
0 1 2 3 4 hello
1 5 6 7 8 world
2 9 10 11 12 foo
'''
#to_csv方法,我们可以将数据写到一个以逗号分隔的文件中
'''
data
something a b c d message
0 one 1 2 3.0 4 NaN
1 two 5 6 NaN 8 world
2 three 9 10 11.0 12 foo
data.to_csv('examples/out.csv')
'''
'''
!cat examples/out.csv
,something,a,b,c,d,message
0,one,1,2,3.0,4,
1,two,5,6,,8,world
2,three,9,10,11.0,12,foo
'''
#read txt
'''
data4.txt
A B C
a 1 2 3
b 4 5 6
'''
x = pd.read_table('data4.txt', sep='\s+') # sep:分隔的正则表达式,表示空格
print x
'''
A B C
a 1 2 3
b 4 5 6
'''
数据清洗和准备
十六、处理缺失数据
缺失数据在pandas中呈现的方式有些不完美,但对于大多数用户可以保证功能正常。对于数值数据,pandas使用浮点值NaN(Not a Number)表示缺失数据。
string_data = pd.Series(['aardvark', 'artichoke', np.nan, 'avocado'])
print string_data
'''
0 aardvark
1 artichoke
2 NaN
3 avocado
dtype: object
'''
print string_data.isnull()
'''
0 False
1 False
2 True
3 False
dtype: bool
'''
十七、滤除缺失数据
过滤掉缺失数据的办法有很多种。你可以通过pandas.isnull或布尔索引的手工方法,但dropna可能会更实用一些。对于一个Series,dropna返回一个仅含非空数据和索引值的Series。
from numpy import nan as NA
data = pd.Series([1, NA, 3.5, NA, 7])
print data.dropna() #== data[data.notnull()]
'''
0 1.0
2 3.5
4 7.0
dtype: float64
'''
#对于DataFrame对象,dropna默认丢弃任何含有缺失值的行
data = pd.DataFrame([[1., 6.5, 3.], [1., NA, NA],[NA, NA, NA], [NA, 6.5, 3.]])
cleaned = data.dropna()
print data
print cleaned
'''
0 1 2
0 1.0 6.5 3.0
1 1.0 NaN NaN
2 NaN NaN NaN
3 NaN 6.5 3.0
0 1 2
0 1.0 6.5 3.0
'''
data.dropna(how='all') #传入how='all'将只丢弃全为NA的那些行
print data
'''
0 1 2
0 1.0 6.5 3.0
1 1.0 NaN NaN
3 NaN 6.5 3.0
'''
#用这种方式丢弃列,只需传入axis=1即可
data[4] = NA
data.dropna(axis=1, how='all')
print data
'''
0 1 2
0 1.0 6.5 3.0
1 1.0 NaN NaN
2 NaN NaN NaN
3 NaN 6.5 3.0
'''
#另一个滤除DataFrame行的问题涉及时间序列数据。假设你只想留下一部分观测数据,
#可以用thresh参数实现此目的。
df = pd.DataFrame(np.random.randn(7, 3))
df.iloc[:4, 1] = NA
df.iloc[:2, 2] = NA
print df
'''
0 1 2
0 -0.204708 NaN NaN
1 -0.555730 NaN NaN
2 0.092908 NaN 0.769023
3 1.246435 NaN -1.296221
4 0.274992 0.228913 1.352917
5 0.886429 -2.001637 -0.371843
6 1.669025 -0.438570 -0.539741
'''
df.dropna(thresh=2)
'''
0 1 2
2 0.092908 NaN 0.769023
3 1.246435 NaN -1.296221
4 0.274992 0.228913 1.352917
5 0.886429 -2.001637 -0.371843
6 1.669025 -0.438570 -0.539741
'''
十九、填充缺失数据
你可能不想滤除缺失数据(有可能会丢弃跟它有关的其他数据),而是希望通过其他方式填补那些“空洞”。对于大多数情况而言,fillna方法是最主要的函数。通过一个常数调用fillna就会将缺失值替换为那个常数值。
df.fillna(0)
print df
'''
0 1 2
0 -0.204708 0.000000 0.000000
1 -0.555730 0.000000 0.000000
2 0.092908 0.000000 0.769023
3 1.246435 0.000000 -1.296221
4 0.274992 0.228913 1.352917
5 0.886429 -2.001637 -0.371843
6 1.669025 -0.438570 -0.539741
'''
#若是通过一个字典调用fillna,就可以实现对不同的列填充不同的值:
df.fillna({1: 0.5, 2: 0})
'''
0 1 2
0 -0.204708 0.500000 0.000000
1 -0.555730 0.500000 0.000000
2 0.092908 0.500000 0.769023
3 1.246435 0.500000 -1.296221
4 0.274992 0.228913 1.352917
5 0.886429 -2.001637 -0.371843
6 1.669025 -0.438570 -0.539741
'''
#fillna默认会返回新对象,但也可以对现有对象进行就地修改
_ = df.fillna(0, inplace=True)
'''
0 1 2
0 -0.204708 0.000000 0.000000
1 -0.555730 0.000000 0.000000
2 0.092908 0.000000 0.769023
3 1.246435 0.000000 -1.296221
4 0.274992 0.228913 1.352917
5 0.886429 -2.001637 -0.371843
6 1.669025 -0.438570 -0.539741
'''
#只要有些创新,你就可以利用fillna实现许多别的功能。
data = pd.Series([1., NA, 3.5, NA, 7])
data.fillna(data.mean())
'''
0 1.000000
1 3.833333
2 3.500000
3 3.833333
4 7.000000
dtype: float64
'''
二十、替换值
利用fillna方法填充缺失数据可以看做值替换的一种特殊情况。replace则提供了一种实现该功能的更简单、更灵活的方式。
data = pd.Series([1., -999., 2., -999., -1000., 3.])
data.replace(-999, np.nan)
'''
0 1.0
1 NaN
2 2.0
3 NaN
4 -1000.0
5 3.0
dtype: float64
'''
data.replace([-999, -1000], np.nan)
'''
0 1.0
1 NaN
2 2.0
3 NaN
4 NaN
5 3.0
dtype: float64
'''
data.replace([-999, -1000], [np.nan, 0])
'''
0 1.0
1 NaN
2 2.0
3 NaN
4 0.0
5 3.0
dtype: float64
'''
二十一、移除重复数据
data = pd.DataFrame({'k1': ['one', 'two'] * 3 + ['two'], 'k2': [1, 1, 2, 3, 3, 4, 4]})
print data
'''
k1 k2
0 one 1
1 two 1
2 one 2
3 two 3
4 one 3
5 two 4
6 two 4
'''
#DataFrame的duplicated方法返回一个布尔型Series,表示各行是否是重复行
data.duplicated()
'''
0 False
1 False
2 False
3 False
4 False
5 False
6 True
dtype: bool
'''
#还有一个与此相关的drop_duplicates方法,它会返回一个DataFrame,重复的数组会标为False
data.drop_duplicates()
'''
k1 k2
0 one 1
1 two 1
2 one 2
3 two 3
4 one 3
5 two 4
'''
#以指定部分列进行重复项判断
data['v1'] = range(7)
data.drop_duplicates(['k1'])
'''
k1 k2 v1
0 one 1 0
1 two 1 1
'''
总结
借鉴书籍《利用Python进行数据分析·第2版》。本文只是列举常用的操作,后期遇到会继续添加。
pandas书籍:《利用Python进行数据分析·第2版》《Pandas Cookbook》