Python数据分析NumPy和pandas(十四、汇总和描述性统计量计算)

pandas 对象有一组常用的数学统计方法,其中大多数属于归纳或汇总统计方法,例如从 Series 中提取单个值(如总和或平均值)的方法,或从 DataFrame 的行或列中提取 Series 值的方法。与 NumPy 数组上的类似方法相比,pandas具有对缺失数据的内置处理方法。

import numpy as np
import pandas as pd

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)

#按column求和
df_column_sum = df.sum()
print(df_column_sum)

#按row求和
df_row_sum = df.sum(axis="columns")
print(df_row_sum)

df输出:

one two
a 1.40 NaN
b 7.10 -4.5
c NaN NaN
d 0.75 -1.3

df.sum()输出:

one    9.25
two   -5.80
dtype: float64

df.sum(axis="columns")输出(其等价于df.sum(axis=1)):

a    1.40
b    2.60
c    0.00
d   -0.55
dtype: float64 

从上面的代码可以看出,在计算时跳过了NaN值,并且如果某行或某列都是NaN时该行或者该列的计算结果为0。我们可以将skipna参数这是为False,这种情况下在某行或某列只要有一个值为NaN,则改行或该列的计算结果就为NaN。例如:

import numpy as np
import pandas as pd

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)

#按column求和,计算时不跳过NaN值
df_column_sum = df.sum(axis="index", skipna=False)
print(df_column_sum)

#按row求和,计算时不跳过NaN值
df_row_sum = df.sum(axis="columns", skipna=False)
print(df_row_sum)

df.sum(axis="index", skipna=False)输出:

one   NaN
two   NaN
dtype: float64

每一列上都有NaN值,所有求sum后,得到一个都是NaN值的Series对象。

df.sum(axis="columns", skipna=False)输出:

a     NaN
b    2.60
c     NaN
d   -0.55
dtype: float64

因为df中b和d行没有NaN值,所以正常进行sum计算,而a和c索引所在的行有NaN值,所以计算结果为NaN。

聚合函数计算(如 mean)需要至少一个非 NaN 值才能产生值结果:

df.mean(axis="columns") 输出:

a    1.400
b    1.300
c      NaN
d   -0.275
dtype: float64

以下是常用方法的一些属性设置列表:

设置项 描述
axis 设置为“index” 时用于 DataFrame 的行(按列方向计算),设置为“columns” 用于列(按行方向计算),也可以设置为整数用于表示沿哪个轴计算
skipna 默认值为True表示跳过NaN值,设置为False表示不排除缺失值
level 如果轴具有分层索引,则按 Level 进行 Reduce 分组 (MultiIndex)

idxmax和idxmin可以获得沿某个轴方向上最大值和最小值所对应的索引(行或列索引),例如对于上面的df对象:df.idxmax() 返回DataFrame对象df沿着列方向统计每列最大值所对应的行索引,输出结果:

one    b
two    d
dtype: object

df.cumsum()累计求和输出:

one two
a 1.40 NaN
b 8.50 -4.5
c NaN NaN
d 9.25 -5.8

使用describe函数,它一次生成多个摘要统计数据 ,例如对于上面的df对象:

df.describe() 输出:

one two
count 3.000000 2.000000
mean 3.083333 -2.900000
std 3.493685 2.262742
min 0.750000 -4.500000
25% 1.075000 -3.700000
50% 1.400000 -2.900000
75% 4.250000 -2.100000
max 7.100000 -1.300000

提醒:对于在整个学习过程中用到的函数方法,大家可以查看官方文档介绍以了解其细节,我在学习过程中,主要介绍这些函数方法的通常用法。 

对于非数值数据,describe 会生成替代汇总统计量,例如下面的Series对象:

obj = pd.Series(["a", "a", "b", "c"] * 4)

obj.describe() 输出:

count      16
unique      3
top            a
freq           8
dtype: object

注意上面构造Series对象obj的时候,我们用来一种新的方法["a", "a", "b", "c"] * 4,将obj打印出来发现这种方法相当于用["a", "a", "b", "c", "a", "a", "b", "c", "a", "a", "b", "c", "a", "a", "b", "c"]创建了obj对象。

下面列表时完整的汇总统计信息和相关方法。

一样,学习过程中可以查阅官方文档对这些方法的介绍。

一、相关性correlation和协方差covariance

一些汇总统计量(如 correlation 和 covariance)是根据成对的参数计算得出的。我们以一些股票的数据,如股票价格和交易量来进行举例计算,这些数据以二进制 Python pickle 文件的形式存储,我们把它加载到DataFrame中来。

import numpy as np
import pandas as pd

price = pd.read_pickle("examples/yahoo_price.pkl")
volume = pd.read_pickle("examples/yahoo_volume.pkl")

加载后price输出: 

AAPL GOOG IBM MSFT
Date
2010-01-04 27.990226 313.062468 113.304536 25.884104
2010-01-05 28.038618 311.683844 111.935822 25.892466
2010-01-06 27.592626 303.826685 111.208683 25.733566
2010-01-07 27.541619 296.753749 110.823732 25.465944
2010-01-08 27.724725 300.709808 111.935822 25.641571
... ... ... ... ...
2016-10-17 117.550003 779.960022 154.770004 57.220001
2016-10-18 117.470001 795.260010 150.720001 57.660000
2016-10-19 117.120003 801.500000 151.259995 57.529999
2016-10-20 117.059998 796.969971 151.520004 57.250000
2016-10-21 116.599998 799.369995 149.630005 59.660000

1714 rows × 4 columns

 加载后volume输出:

AAPL GOOG IBM MSFT
Date
2010-01-04 123432400 3927000 6155300 38409100
2010-01-05 150476200 6031900 6841400 49749600
2010-01-06 138040000 7987100 5605300 58182400
2010-01-07 119282800 12876600 5840600 50559700
2010-01-08 111902700 9483900 4197200 51197400
... ... ... ... ...
2016-10-17 23624900 1089500 5890400 23830000
2016-10-18 24553500 1995600 12770600 19149500
2016-10-19 20034600 116600 4632900 22878400
2016-10-20 24125800 1734200 4023100 49455600
2016-10-21 22384800 1260500 4401900 79974200

1714 rows × 4 columns

 现在,我们按照时间序列计算价格的百分比变化,并输出最后5行:

import numpy as np
import pandas as pd

price = pd.read_pickle("examples/yahoo_price.pkl")
volume = pd.read_pickle("examples/yahoo_volume.pkl")

returns = price.pct_change()
print(returns.tail())

输出:

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 中重叠的、非NaN的按索引对齐的值的相关性。cov方法计算协方差 。例如:

import numpy as np
import pandas as pd

price = pd.read_pickle("examples/yahoo_price.pkl")
volume = pd.read_pickle("examples/yahoo_volume.pkl")

returns = price.pct_change()

#计算MSFT于IBM股票价格的相关性
a = returns["MSFT"].corr(returns["IBM"])
#计算MSFT于IBM股票价格的协方差
b = returns["MSFT"].cov(returns["IBM"])
print(a)
print(b)

 输出结果:

0.49976361144151144

8.870655479703546e-05

DataFrame 的 corr 和 cov 方法分别以 DataFrame 的形式返回完全相关或协方差矩阵

import numpy as np
import pandas as pd

price = pd.read_pickle("examples/yahoo_price.pkl")
volume = pd.read_pickle("examples/yahoo_volume.pkl")

returns = price.pct_change()

print(returns.corr())
print(returns.cov())

输出:

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
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 方法,可以计算 DataFrame 的列或行与另一个 Series 或 DataFrame 之间的成对相关性。传递 Series 将返回一个 Series,其中包含为每列计算的相关值 。例如:

import numpy as np
import pandas as pd

price = pd.read_pickle("examples/yahoo_price.pkl")
volume = pd.read_pickle("examples/yahoo_volume.pkl")

returns = price.pct_change()

res = returns.corrwith(returns["IBM"])
print(res)

 输出:

AAPL      0.386817
GOOG    0.405099
IBM        1.000000
MSFT     0.499764
dtype: float64

在corrwith方法中传递 DataFrame 会计算匹配列名的相关性。下面我们计算了价格百分比变化与成交量volume的相关性:

import numpy as np
import pandas as pd

price = pd.read_pickle("examples/yahoo_price.pkl")
volume = pd.read_pickle("examples/yahoo_volume.pkl")

returns = price.pct_change()

res = returns.corrwith(volume)
print(res)

 输出:

AAPL     -0.075565
GOOG   -0.007067
IBM       -0.204849
MSFT    -0.092950
dtype: float64

在corrwith中传递 axis=“columns” 会逐行执行操作。任何情况下,在计算相关性之前,数据点都会按标签对齐。

二、Unique Values、Value Counts 和 Membership

对于一维的Series,获取其中的唯一值使用unique函数,例如:

import numpy as np
import pandas as pd

obj = pd.Series(["c", "a", "d", "a", "a", "b", "b", "c", "c"])
uniques = obj.unique()
print(uniques)

输出:['c' 'a' 'd' 'b']

唯一值不一定按照它们第一次出现的顺序返回,也不按排序顺序返回,但如果需要,可以在事后对它们进行排序 uniques.sort()。与此类似,value_counts 计算输出包含值出现频率 的 Series:

obj.value_counts() 输出(默认按降序):

c    3
a    3
b    2
d    1
Name: count, dtype: int64

value_counts方法也可以作为顶级 pandas 方法使用,可以与 NumPy 数组或其他 Python 序列一起使用,例如:pd.value_counts(obj.to_numpy(), sort=False) 输出:

c    3
a    3
d    1
b    2
Name: count, dtype: int64

这里指定了sort=False 不排序。

isin方法可以对Series和DataFrame中的元素进行筛查,结果可以是从 DataFrame中筛选出的 Series 或 column 中的子集 。

import numpy as np
import pandas as pd

obj = pd.Series(["c", "a", "d", "a", "a", "b", "b", "c", "c"])
print(obj)
mask = obj.isin(["b", "c"])
print(mask)
print(obj[mask])

输出:

0    c
1    a
2    d
3    a
4    a
5    b
6    b
7    c
8    c
dtype: object
0     True
1    False
2    False
3    False
4    False
5     True
6     True
7     True
8     True
dtype: bool
0    c
5    b
6    b
7    c
8    c
dtype: object

Index.get_indexer 方法进行索引筛查,例如:

import numpy as np
import pandas as pd

to_match = pd.Series(["c", "a", "b", "b", "c", "a"])
unique_vals = pd.Series(["c", "b", "a"])

indices = pd.Index(unique_vals).get_indexer(to_match)
print(indices)

输出:[0 2 1 1 0 2]

以上方法的应用可以参考以下列表:

计算DataFrame的直方图:

import numpy as np
import pandas as pd

data = pd.DataFrame({"Qu1": [1, 3, 4, 3, 4], 
                     "Qu2": [2, 3, 1, 2, 3], 
                     "Qu3": [1, 5, 2, 4, 4]})

#单列计数并排序
one_col = data["Qu1"].value_counts().sort_index()

#计算所有列的这个值,将pandas.value_counts传递给DataFrame的apply方法
all_col = data.apply(pd.value_counts).fillna(0)

print(one_col)
print(all_col)

 输出:

Qu1
1     1
3     2
4     2
Name: count, dtype: int64

   Qu1  Qu2  Qu3
1  1.0  1.0  1.0
2  0.0  2.0  1.0
3  2.0  2.0  0.0
4  2.0  0.0  2.0
5  0.0  0.0  1.0

结果中的行标签1 2 3 4 5是所有列中出现的不同值。元素值是每列中这些值出现次数的计数。

还有一个 DataFrame.value_counts 方法,但它将 DataFrame 的每一行视为 Tuples 来计数,以确定每个不同行的出现次数: 

import numpy as np
import pandas as pd

data = pd.DataFrame({"a": [1, 1, 1, 2, 2], "b": [0, 0, 1, 0, 0]})
res = data.value_counts()
print(data)
print(res)

输出:

a b
0 1 0
1 1 0
2 1 1
3 2 0
4 2 0

a  b
1  0    2
2  0    2
1  1    1
Name: count, dtype: int64


以上对于pandas的基础功能学习就到此。下一次我将学习使用 pandas 读取(或加载)和写入数据集的工具。然后,将更深入地研究使用 pandas 进行数据清理、整理、分析和可视化工具

猜你喜欢

转载自blog.csdn.net/FreedomLeo1/article/details/143258420