[TOC]
Index对象是不可更改的(immutable)。index[1]=\'d\'
就会出错。但是,df.index=index_new
是可以的。
对于reindex
可以修改(行)索引、列,或两个都修改。1frame.reindex(columns=states)
重新索引列。
df.drop([list1,list2])
默认是删除的指定的行,如果想要删除某一列,就需要df.drop([list1,list2],axis=1)
。
自己的认识,axis
是指查找数据的一个方向,axis=0
是指查找数据时是竖直方向去找,axis=1
是水平方向去找数据。这样,这里想要删除某一列,就需要是水平方向去找到该列名。否则,提示找不到。
Series索引,Series索引值不止是整数。
obj = Series(np.arange(4.), index=[\'a\', \'b\', \'c\', \'d\'])
obj[0]
obj[:2] #找到:obj[0],obj[1]
obj[\'a\']
obj[[\'a\',\'c\']]
obj[\'a\':\'c\'] #找到:obj[0],obj[1],obj[2] 标签索引,闭区间!
以上索引方式都可以。
利用标签的切片运算和普通的Python切片运算是不同的,其末端是包含的(inclusive)。闭区间
对DataFrame索引其实就是获取一个或多个列。
data = DataFrame(np.arange(16).reshape((4, 4)),
index=[\'Ohio\', \'Colorado\', \'Utah\', \'New York\'],
columns=[\'one\', \'two\', \'three\', \'four\'])
data[\'two\']
data[[\'three\',\'one\']]
这时候,不能像Series
那样直接选取行了,如:data[\'Ohio\']
那么,选择行怎么做呢?
# 这里举例选取前三行
data[:3] 选取了0,1,2行
# 或者
data.ix[\'Ohio\':\'Utah\',:]
# 或者
data.ix[0:3]
# 或者
data.loc[\'Ohio\':\'Utah\',:]
# 或者
data.iloc[0:3,:]
以上,
后边的冒号可以省略。
ix标签索引,位置索引都可以
loc标签索引
iloc位置索引
再强调一遍,标签索引是闭区间!
布尔索引
data[data[\'three\']>5]
data[data<5]
data.ix[data.three>5,:3]
总结下来,ix
索引最牛逼!灵活结合了标签索引和位置索引!
pandas最重要的一个功能是,它可以对不同索引的对象进行算数运算。
对于DataFrame,对齐操作将会同时发生在行和列上。
没有重叠的位置会产生NA
值–NaN
。
广播功能,需要注意索引,如果某个索引值在DataFrame或者Series的索引中找不到,则参与运算就会容易形成NA
值。
如果希望匹配行且在列上广播,则必须使用算术运算方法。例如:
series3 = frame[\'d\']
frame.sub(series3, axis=0)
结果:
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 |
元素及的Python函数也是可以的。假如想得到frame中各个浮点值的格式化字符串,使用applymap
函数。
frame = DataFrame(np.random.randn(4, 3), columns=list(\'bde\'),
index=[\'Utah\', \'Ohio\', \'Texas\', \'Oregon\'])
format = lambda x: \'%.2f\' % x
frame.applymap(format)
之所以叫applymap
,是因为Series有一个应用于元素级函数的map方法:
frame[\'e\'].map(format)
虽然许多pandas函数(如reindex)都要求标签唯一,但这并不是强制的。
obj = Series(range(5), index=[\'a\', \'a\', \'b\', \'b\', \'c\'])
obj.index.is_unique #False
索引的`is_unique属性可以告诉你它的值是否唯一。obj[\'a\']
会返回两个值。
NA
值会自动被排除。通过skipna
选项可以禁用该功能。
意思是,df.mean(axis=1,skipna=False)
会计算水平方向的均值,并且,有NA
出现,均值也会是NA
,而不是忽视它。
idxmin
返回最小值的索引
idxman
返回最大值的索引
有些汇总统计是通过参数对计算出来的。
看几个DataFrame,他们的数据来自Yahoo!Finance的股票价格和成交量。
import pandas.io.data as web
all_data = {}
for ticker in [\'AAPL\', \'IBM\', \'MSFT\', \'GOOG\']:
all_data[ticker] = web.get_data_yahoo(ticker)
price = DataFrame({tic: data[\'Adj Close\']
for tic, data in all_data.iteritems()})
volume = DataFrame({tic: data[\'Volume\']
for tic, data in all_data.iteritems()})
计算价格的百分数变化:
returns = price.pct_change()
Series的corr
方法计算两个Series中重叠的、非NA的、按索引对齐的值的相关系数。与此类似,cov
用于计算协方差。
returns.MSFT.corr(returns.IBM)
returns.MSFT.cov(returns.IBM)
利用DataFrame的corrwith
方法,可以计算其列或行跟另一个Series或者DataFrame之间的相关系数。
returns.corrwith(returns.IBM)
#等价于
returns.corr()[\'IBM\']
无论如何,在计算相关系数之前,所有的数据项都会按标签对齐。
unique
函数可以得到Series中唯一值数组。
value_counts
函数用于计算Series中各值出现的频率。
isin
用于选取矢量化集合的成员资格。
这几个函数都是Series数据的方法!
result = data.apply(pd.value_counts).fillna(0)
利用上面这个方法,可以对df数据每列出现的数值频率进行统计,同时,对有的列中没有出现的数值的频率为NA的值设置为0
apply
看来这个函数还是很有用啊,它是默认从列角度(axis=0)去应用里边的函数。而applymap
是元素级应用函数。
之前看一篇文章,机器学习系列(3)_逻辑回归应用之Kaggle泰坦尼克之灾2,当中遇到缺失数据之后,运用机器学习的方法,结合其他变量拟合预测出值,然后作为缺失值的填充。
而本书立足于数据分析,从处理数据角度出发,因此,不会采用那么复杂的方法。这里,是要介绍一些操作数据的函数方法,这是基础,是之后处理数据的基本功!缺失数据也是重中之重!
pandas的设计目标之一就是让缺失数据的处理任务尽量轻松。例如,pandas对象上的描述统计都排除了缺失数据!
string_data = Series([\'aardvark\', \'artichoke\', np.nan, \'avocado\'])
string_data
0 aardvark
1 artichoke
2 NaN
3 avocado
dtype: object
Python内置的None值也会被当做NA处理。
dropna
方法可能比较实用一点。
from numpy import nan as NA
data = Series([1, NA, 3.5, NA, 7])
data.dropna()
对于一个Series, dropna
返回一个仅含非空数据和索引值的Series。
0 1.0
2 3.5
4 7.0
dtype: float64
而对于一个DataFrame对象,事情就有点复杂了。dropna
默认丢弃任何含有缺失值的行。
data = DataFrame([[1., 6.5, 3.], [1., NA, NA],
[NA, NA, NA], [NA, 6.5, 3.]])
cleaned = data.dropna()
data
cleaned
0 1 2
0 1.0 6.5 3.0
传入how=\'all\'
将只丢弃全为NA的行。要用这种方式丢弃列,只需要传入参数axis=1
。
data.dropna(how=\'all\')
0 1 2
0 1.0 6.5 3.0
1 1.0 NaN NaN
3 NaN 6.5 3.0
另一个滤除DataFrame行的问题涉及时间序列。假设只想留下一部分观测数据,可以用tresh
参数实现。
df = DataFrame(np.random.randn(7, 3))
df.ix[:4, 1] = NA; df.ix[:2, 2] = NA
df
0 1 2
0 -0.577087 NaN NaN
1 0.523772 NaN NaN
2 -0.713544 NaN NaN
3 -1.860761 NaN 0.560145
4 -1.265934 NaN -1.063512
5 0.332883 -2.359419 -0.199543
6 -1.541996 -0.970736 -1.307030
df.dropna(thresh=3)
保留至少3个非空值的行。
0 1 2
5 0.332883 -2.359419 -0.199543
6 -1.541996 -0.970736 -1.307030
对于大多数情况而言,fillna
方法是最主要的函数。通过一个常数调用fillna
就会将缺失值替换为那个常数。df.fillna(0)
。
若是通过一个字典调用fillna
,就可以实现对不同的列填充不同的值。
df.fillna({1:0.5,3:-1})
fillna默认会返回新对象,但也可以对现有对象进行就地修改:
df.fillna(0,inplace=True)
对reindex
有效地那些插值方法,也可用以fillna
。
df = DataFrame(np.random.randn(6, 3))
df.ix[2:, 1] = NA; df.ix[4:, 2] = NA
df
df.fillna(method=\'ffill\', limit=2)
# 有很多灵活的填充方式
data = Series([1., NA, 3.5, NA, 7])
data.fillna(data.mean())
层次化索引(hierarchical indexing)是pandas的一项重要功能,它使你能在一个轴上拥有多个(两个以上)索引级别。
抽象点说,它使你能以低纬度形式处理高纬度数据。
data = Series(np.random.randn(10),
index=[[\'a\', \'a\', \'a\', \'b\', \'b\', \'b\', \'c\', \'c\', \'d\', \'d\'],
[1, 2, 3, 1, 2, 3, 1, 2, 2, 3]])
data
a 1 -0.204708
2 0.478943
3 -0.519439
b 1 -0.555730
2 1.965781
3 1.393406
c 1 0.092908
2 0.281746
d 2 0.769023
3 1.246435
dtype: float64
这段数据可以通过其unstack
方法被重新安排到一个DataFrame中:
data.unstack()
1 2 3
a -0.204708 0.478943 -0.519439
b -0.555730 1.965781 1.393406
c 0.092908 0.281746 NaN
d NaN 0.769023 1.246435
unstack
的逆方法是stack
.
不要将索引名称(index.names)跟轴标签混为一谈!
有时,你需要重新调整某条轴上各级别的顺序,或根据指定级别上的值对数据进行排序。
swaplevel
接受两个级别编号或名称,并返回一个互换了级别的新对象(但数据不会发生变化)
许多对DataFrame和Series的描述和汇总统计都有一个level
选项,它用于指定在某条轴上求和的级别。
这其实是利用了pandas的groupby功能。
人们经常想要将DataFrame的一个或多个列当做行索引来用,或者可能希望将行索引变成DataFrame的列。
frame = DataFrame({\'a\': range(7), \'b\': range(7, 0, -1),
\'c\': [\'one\', \'one\', \'one\', \'two\', \'two\', \'two\', \'two\'],
\'d\': [0, 1, 2, 0, 1, 2, 3]})
frame
DataFrmae的set_index
函数会将其一个或多个列转换为行索引,并创建一个新的DataFrame:
frame2 = frame.set_index([\'c\', \'d\'])
默认情况下,那系列会从DataFrame中移除,但也可以将其保留下来。
frame.set_index([\'c\', \'d\'], drop=False)
reset_index
的功能跟set_index
刚好相反,层次化索引的级别会被转移到列里边。
frame2.reset_index()