书接上文~~

函数运用和映射

numpy的通用函数也能够对pandas目标操作:

In [190]: frame = pd.DataFrame(np.random.randn(4, 3), columns=list('bde'),
   .....:                      index=['Utah', 'Ohio', 'Texas', 'Oregon'])
In [191]: frame
Out[191]: 
               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
In [192]: np.abs(frame)
Out[192]: 
               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办法即可完成此功用:

In [193]: f = lambda x: x.max() - x.min()
In [194]: frame.apply(f)
Out[194]: 
b    1.802165
d    1.684034
e    2.689627
dtype: float64

这儿的函数f,核算了一个Series的最大值和最小值的差,在frame的每列都执行了一次。成果是一个Series,运用frame的列作为索引

假如传递axis=’columns’到apply,这个函数会在每行执行:

In [195]: frame.apply(f, axis='columns')
Out[195]:
Utah      0.998382
Ohio      2.521511
Texas     0.676115
Oregon    2.542656
dtype: float64

传递到apply的函数不是必须回来一个标量,还能够回来由多个值组成的Series:

In [196]: def f(x):
   .....:     return pd.Series([x.min(), x.max()], index=['min', 'max'])
In [197]: frame.apply(f)
Out[197]: 
            b         d         e
min -0.555730  0.281746 -1.296221
max  1.246435  1.965781  1.393406

排序和排名

排序一直都是数据中不行缺少的部分。要对行或列索引进行排序,能够运用sort_index办法,它将回来一个现已排序的新目标:

In [201]: obj = pd.Series(range(4), index=['d', 'a', 'b', 'c'])
In [202]: obj.sort_index()
Out[202]:
a    1
b    2
c    3
d    0
dtype: int64

上面是针对Series,当然关于DataFrame也有相似操作:

In [203]: frame = pd.DataFrame(np.arange(8).reshape((2, 4)),
   .....:                      index=['three', 'one'],
   .....:                      columns=['d', 'a', 'b', 'c'])
In [204]: frame.sort_index()
Out[204]: 
       d  a  b  c
one    4  5  6  7
three  0  1  2  3
In [205]: frame.sort_index(axis=1)
Out[205]:
       a  b  c  d
three  1  2  3  0
one    5  6  7  4

数据默许是按升序排序的,但也能够降序排序:

In [206]: frame.sort_index(axis=1, ascending=False)
Out[206]: 
       d  c  b  a
three  0  3  2  1
one    4  7  6  5

若要按值对Series进行排序,可运用其sort_values办法:

In [207]: obj = pd.Series([4, 7, -3, 2])
In [208]: obj.sort_values()
Out[208]: 
2   -3
3    2
0    4
1    7
dtype: int64

当排序一个DataFrame时,你或许期望依据一个或多个列中的值进行排序。将一个或多个列的姓名传递给sort_values的by选项即可达到该意图:

In [211]: frame = pd.DataFrame({'b': [4, 7, -3, 2], 'a': [0, 1, 0, 1]})
In [212]: frame
Out[212]: 
   a  b
0  0  4
1  1  7
2  0 -3
3  1  2
In [213]: frame.sort_values(by='b')
Out[213]: 
   a  b
2  0 -3
3  1  2
0  0  4
1  1  7

说完排序,接下来是排名,所谓排名就是指对数组从1到有效数据点总数分配名次的操作。Series和DataFrame的rank办法就是完成排名的函数办法。默许状况下,rank经过将平均排名分配到每个组来打破平级关系:

In [215]: obj = pd.Series([7, -5, 7, 4, 2, 0, 4])
In [216]: obj.rank()
Out[216]: 
0    6.5
1    1.0
2    6.5
3    4.5
4    3.0
5    2.0
6    4.5
dtype: float64

简而言之就是对数据进行排大小。小的从1开始,大的在后,呈现重复的就取平均值。也能够依据值在原数据中呈现的次序给出排名:

In [217]: obj.rank(method='first')
Out[217]: 
0    6.0
1    1.0
2    7.0
3    4.0
4    3.0
5    2.0
6    5.0
dtype: float64

这儿,条目0和2没有运用平均排名6.5,它们被设成了6和7,因为数据中标签0坐落标签2的前面。

当然你也能够倒序摆放,同样也能够在DataFrame中运用:

In [219]: frame = pd.DataFrame({'b': [4.3, 7, -3, 2], 'a': [0, 1, 0, 1],
   .....:                       'c': [-2, 5, 8, -2.5]})
In [220]: frame
Out[220]: 
   a    b    c
0  0  4.3 -2.0
1  1  7.0  5.0
2  0 -3.0  8.0
3  1  2.0 -2.5
In [221]: frame.rank(axis='columns')
Out[221]: 
     a    b    c
0  2.0  3.0  1.0
1  1.0  3.0  2.0
2  2.0  1.0  3.0
3  2.0  3.0  1.0

图5-3展现了在排序中呈现平级(数值相同)的状况下如何区别先后的办法。

啃书:《利用python进行数据分析》第五章——pandas入门(三)

图5-3 破坏平级状况method值

带有重复标签的轴索引

当咱们的标签呈现重复的时候该怎么办?咱们来看看下面这个简略的带有重复索引值的Series:

In [222]: obj = pd.Series(range(5), index=['a', 'a', 'b', 'b', 'c'])
In [223]: obj
Out[223]: 
a    0
a    1
b    2
b    3
c    4
dtype: int64

索引的is_unique特点能够告知你它的值是否是仅有的:

In [224]: obj.index.is_unique
Out[224]: False

关于带有重复值的索引,数据选取的行为将会有些不同。假如某个索引对应多个值,则回来一个Series;而对应单个值的,则回来一个标量值:

In [225]: obj['a']
Out[225]: 
a    0
a    1
dtype: int64
In [226]: obj['c']
Out[226]: 4

这样会使代码变复杂,因为索引的输出类型会依据标签是否有重复发生变化。对DataFrame的行进行索引时也是如此。所以咱们在运用中尽量避免轴索引重复的状况。

5.3描述性核算的概述与核算

pandas具有一组常用的数学和核算办法。其中大部分归于归约或汇总核算的分类。这些办法从DataFrame的行或列中抽取一个Series或一系列值的单个值(例如核算和或平均值)。与Numpy数组中的相似办法比较,它们内建了处理丢失值的功用。关于一个小型的DataFrame:

In [230]: 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'])
In [231]: df
Out[231]: 
    one  two
a  1.40  NaN
b  7.10 -4.5
c   NaN  NaN
d  0.75 -1.3

调用DataFrame的sum办法将会回来一个含有列的和的Series:

In [232]: df.sum()
Out[232]: 
one    9.25
two   -5.80
dtype: float64

传入axis=’columns’或axis=1将会按行进行求和运算:

In [233]: df.sum(axis=1)
Out[233]:
a    1.40
b    2.60
c     NaN
d   -0.55

NA值会自动被扫除,除非整个切片(这儿指的是行或列)都是NA。经过skipna选项能够禁用该功用:

In [234]: df.mean(axis='columns', skipna=False)
Out[234]: 
a      NaN
b    1.300
c      NaN
d   -0.275
dtype: float64

下图5-4 列出了归约办法的常用参数

啃书:《利用python进行数据分析》第五章——pandas入门(三)

图5-4 归约办法的常用参数

还有很多办法就不逐个展现,下图5-5 展现了汇总核算相关办法的列表展现。

啃书:《利用python进行数据分析》第五章——pandas入门(三)

图5-5 核算办法列表

相关性和协方差

汇总核算,例如有相关性和协方差,这些都是很多个参数核算出来的。咱们来看一个实践的数据例子,它们来自Yahoo!Finance的股票价格和成交量,这儿的数据集有需求能够找我私信拿:

In [240]: price = pd.read_pickle('examples/yahoo_price.pkl')
In [241]: volume = pd.read_pickle('examples/yahoo_volume.pkl')
In [242]: returns = price.pct_change()
In [243]: returns.tail()
Out[243]: 
                AAPL      GOOG       IBM      MSFT
Date                                              
2016-10-17 -0.000680  0.001837  0.002072 -0.003483
2016-10-18 -0.000681  0.019616 -0.026168  0.007690
2016-10-19 -0.002979  0.007846  0.003583 -0.002255
2016-10-20 -0.000512 -0.005652  0.001719 -0.004867
2016-10-21 -0.003930  0.003011 -0.012474  0.042096

此处核算了数据价格中的百分比占比。

Series的corr办法用于核算两个Series中堆叠的、非NA的、按索引对齐的值的相关系数。与此相似,cov用于核算协方差:

In [244]: returns['MSFT'].corr(returns['IBM'])
Out[244]: 0.49976361144151144
In [245]: returns['MSFT'].cov(returns['IBM'])
Out[245]: 8.8706554797035462e-05

因为MSTF是一个合理的Python特点,咱们还能够用更简练的语法挑选列:

In [246]: returns.MSFT.corr(returns.IBM)
Out[246]: 0.49976361144151144

另一方面,DataFrame的corr和cov办法将以DataFrame的形式分别回来完整的相关系数或协方差矩阵:

In [247]: returns.corr()
Out[247]: 
          AAPL      GOOG       IBM      MSFT
AAPL  1.000000  0.407919  0.386817  0.389695
GOOG  0.407919  1.000000  0.405099  0.465919
IBM   0.386817  0.405099  1.000000  0.499764
MSFT  0.389695  0.465919  0.499764  1.000000
In [248]: returns.cov()
Out[248]: 
          AAPL      GOOG       IBM      MSFT
AAPL  0.000277  0.000107  0.000078  0.000095
GOOG  0.000107  0.000251  0.000078  0.000108
IBM   0.000078  0.000078  0.000146  0.000089
MSFT  0.000095  0.000108  0.000089  0.000215

使用DataFrame的corrwith办法,你能够核算其列或行跟另一个Series或DataFrame之间的相关系数。传入一个Series将会回来一个相关系数值Series(针对各列进行核算):

In [249]: returns.corrwith(returns.IBM)
Out[249]: 
AAPL    0.386817
GOOG    0.405099
IBM     1.000000
MSFT    0.499764
dtype: float64

传入一个DataFrame则会核算按列名配对的相关系数。这儿,我核算百分比变化与成交量的相关系数:

In [250]: returns.corrwith(volume)
Out[250]: 
AAPL   -0.075565
GOOG   -0.007067
IBM    -0.204849
MSFT   -0.092950
dtype: float64

传入axis=’columns’即可按行进行核算。无论如何,在核算相关系数之前,一切的数据项都会按标签对齐。

仅有值、计数和成员特点

另一类办法就是在从一维的Series包括的数值中提取信息。为了阐明简略,下面举个例子:

In [251]: obj = pd.Series(['c', 'a', 'd', 'a', 'a', 'b', 'b', 'c', 'c'])

第一个函数是unique,它能够得到Series中的仅有值数组:

In [252]: uniques = obj.unique()
In [253]: uniques
Out[253]: array(['c', 'a', 'd', 'b'], dtype=object)

回来的仅有值是未排序的,假如需求的话,能够对成果再次进行排序(uniques.sort())。相似的,value_counts用于核算一个Series中各值呈现的频率:

In [254]: obj.value_counts()
Out[254]: 
c    3
a    3
b    2
d    1
dtype: int64

为了便于查看,成果Series是按值频率降序摆放的。value_counts还是一个尖端pandas办法,可用于任何数组或序列:

In [255]: pd.value_counts(obj.values, sort=False)
Out[255]: 
a    3
b    2
c    3
d    1
dtype: int64

isin用于判别矢量化调集的成员资格,可用于过滤Series中或DataFrame列中数据的子集:

In [256]: obj
Out[256]: 
0    c
1    a
2    d
3    a
4    a
5    b
6    b
7    c
8    c
dtype: object
In [257]: mask = obj.isin(['b', 'c'])
In [258]: mask
Out[258]: 
0     True
1    False
2    False
3    False
4    False
5     True
6     True
7     True
8     True
dtype: bool
In [259]: obj[mask]
Out[259]: 
0    c
5    b
6    b
7    c
8    c
dtype: object

与isin相似的是Index.get_indexer办法,它能够给你一个索引数组,从或许包括重复值的数组到另一个不同值的数组:

In [260]: to_match = pd.Series(['c', 'a', 'b', 'b', 'c', 'a'])
In [261]: unique_vals = pd.Series(['c', 'b', 'a'])
In [262]: pd.Index(unique_vals).get_indexer(to_match)
Out[262]: array([0, 2, 1, 1, 0, 2])

图5-6 给出了这几个办法的一些参阅信息。

啃书:《利用python进行数据分析》第五章——pandas入门(三)

图5-6 常见办法参阅

总结

本章就大约这样,鄙人一章,咱们将讨论用pandas读取(或加载)和写入数据集的东西。之后,咱们将更深入地研讨运用pandas进行数据清洗、规整、分析和可视化东西。