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 进行数据清理、整理、分析和可视化工具