Pandas库
引子
Numpy 在向量化的数值计算中表现优异
但是在处理更灵活、复杂的数据任务:
如为数据添加标签、处理缺失值、分组和透视表等方面
Numpy显得力不从心
而基于Numpy构建的Pandas库,提供了使得数据分析变得更快更简单的高级数据结构和操作工具
11.1 对象创建
11.1.1 Pandas Series 对象
Series 是带标签数据的一维数组
Series 对象的创建
通用结构: pd.Series(data, index=index, dtype=dtype)
data:数据,可以是列表、字典或Numpy数组
index:索引,为可选参数
dtype:数据类型,为可选参数
1 用列表创建
- index缺省,默认为整数序列
import pandas as pd
data = pd.Series([1.5, 3, 4.5, 6])
print(data)
0 1.5
1 3.0
2 4.5
3 6.0
dtype: float64
- 增加index
data = pd.Series([1.5, 3, 4.5, 6], index=["a", "b", "c", "d"])
print(data)
a 1.5
b 3.0
c 4.5
d 6.0
dtype: float64
- 增加数据类型
缺省则从传入数据自动判断
data = pd.Series([1, 2, 3, 4], index=["a", "b", "c", "d"], dtype=float)
print(data)
a 1.0
b 2.0
c 3.0
d 4.0
dtype: float64
注意:数据支持多种数据类型
data = pd.Series([1, 2, "3", 4], index=["a", "b", "c", "d"])
print(data)
a 1
b 2
c 3
d 4
dtype: object
print(data["a"])
print(data["c"])
1
3
数据类型可被强制改变
data = pd.Series([1, 2, "3", 4], index=["a", "b", "c", "d"], dtype=float)
print(data)
a 1.0
b 2.0
c 3.0
d 4.0
dtype: float64
print(data["c"])
3.0
如果不可强制转换,则会报错
data = pd.Series([1, 2, "a", 4], index=["a", "b", "c", "d"], dtype=float)
print(data)
2 用一维Numpy数组创建
import pandas as pd
import numpy as np
x = np.arange(5)
y = pd.Series(x)
print(y)
0 0
1 1
2 2
3 3
4 4
dtype: int32
3 用字典创建
- 默认以键为index,值为data
population_dict = {"BeiJing": 2154,
"ShangHai": 2424,
"ShenZhen": 1303,
"HangZhou": 981 }
population = pd.Series(population_dict)
print(population)
BeiJing 2154
ShangHai 2424
ShenZhen 1303
HangZhou 981
dtype: int64
- 字典创建,如果指定index,则会到字典中的键中筛选,找不到的,值设为NaN
population = pd.Series(population_dict, index=["BeiJing", "HangZhou", "c", "d"])
print(population)
BeiJing 2154.0
HangZhou 981.0
c NaN
d NaN
dtype: float64
4 data为标量的情况
print(pd.Series(5, index=[100, 200, 300]))
100 5
200 5
300 5
dtype: int64
11.1.2 Pandas DataFrame对象
DataFrame 是带标签数据的多维数组
DataFrame对象的创建
通用结构:pd.DataFrame(data, index=index, columns=columns)
data:数据,可以是列表,字典或Numpy数组
index:索引,为可选参数
columns:列标签,为可选参数
1 通过Series对象创建
population_dict = {"BeiJing": 2154,
"ShangHai": 2424,
"ShenZhen": 1303,
"HangZhou": 981}
population = pd.Series(population_dict)
print(pd.DataFrame(population))
print(pd.DataFrame(population, columns=["population"]))
2 通过Series对象字典创建
population_dict = {"BeiJing": 2154,
"ShangHai": 2424,
"ShenZhen": 1303,
"HangZhou": 981}
population = pd.Series(population_dict)
GDP_dict = {"BeiJing": 30320,
"ShangHai": 32680,
"ShenZhen": 24222,
"HangZhou": 13468}
GDP = pd.Series(GDP_dict)
print(pd.DataFrame({"population": population,
"GDP": GDP}))
注意:数量不够的会自动补齐
print(pd.DataFrame({"population": population,
"GDP": GDP,
"Country": "China"}))
3 通过字典列表对象创建
- 字典索引作为index, 字典键作为columns
data = [{"a": i, "b": 2*i} for i in range(3)]
print(data)
print(pd.DataFrame(data))
- 不存在的键,会默认值为NaN
data = [{"a": 1, "b": 1}, {"b":3, "c": 4}]
print(pd.DataFrame(data))
4 通过Numpy二维数组创建
print(pd.DataFrame(np.random.randint(10, size=(3, 2)), columns=["foo", "bar"], index=["a", "b", "c"]))
11.2 DataFrame的性质
11.2.1 属性
data = pd.DataFrame({"population":population, "GDP": GDP})
print(data)
1. df.values 返回numpy数组表示的数据
print(data.values)
[[ 2154 30320]
[ 2424 32680]
[ 1303 24222]
[ 981 13468]]
2. df.index 返回行索引
print(data.index)
Index([‘BeiJing’, ‘ShangHai’, ‘ShenZhen’, ‘HangZhou’], dtype=‘object’)
3. df.columns 返回列索引
print(data.columns)
Index([‘population’, ‘GDP’], dtype=‘object’)
4. df.shape 形状
print(data.shape)
(4, 2)
5. pd.size 大小
print(data.size)
8
6. pd.dtypes 返回每列数据类型
print(data.dtypes)
population int64
GDP int64
dtype: object
11.2.2 索引
1. 获取列
- 字典式
print(data["population"])
BeiJing 2154
ShangHai 2424
ShenZhen 1303
HangZhou 981
Name: population, dtype: int64
print(data[["GDP", "population"]]) # 多个列获取用列表形式
- 对象属性式
print(data.GDP)
BeiJing 30320
ShangHai 32680
ShenZhen 24222
HangZhou 13468
Name: GDP, dtype: int64
2. 获取行
- 绝对索引 df.loc
print(data.loc["BeiJing"])
population 2154
GDP 30320
Name: BeiJing, dtype: int64
print(data.loc[["BeiJing", "HangZhou"]])
- 相对索引
print(data.iloc[0])
population 2154
GDP 30320
Name: BeiJing, dtype: int64
print(data.iloc[[1, 3]])
3. 获取标量
print(data.loc["BeiJing", "GDP"])
30320
print(data.iloc[0, 1])
30320
print(data.values[0][1])
30320
4. Series对象的索引
print(type(data.GDP))
<class ‘pandas.core.series.Series’>
print(GDP["BeiJing"])
30320
11.2.3 切片
dates = pd.date_range(start='2019-01-01', periods=6)
print(dates)
DatetimeIndex([‘2019-01-01’, ‘2019-01-02’, ‘2019-01-03’, ‘2019-01-04’,
‘2019-01-05’, ‘2019-01-06’],
dtype=‘datetime64[ns]’, freq=‘D’)
df = pd.DataFrame(np.random.randn(6, 4), index=dates, columns=["A", "B", "C", "D"])
print(df)
1. 行切片
print(df["2019-01-01": "2019-01-03"])
print(df.loc["2019-01-01": "2019-01-03"])
print(df.iloc[0:3]) # 不包含结束位置
2. 列切片
print(df.loc[:, "A": "C"])
print(df.iloc[:, 0: 3])
3. 多种多样的取值
- 行、列同时切片
print(df.loc["2019-01-02": "2019-01-03", "C": "D"]) # 行列同时切片
print(df.iloc[1: 3, 2:])
- 行切片,列分散取值
print(df.loc["2019-01-04": "2019-01-06", ["A", "C"]]) # 行切片,列分散取值
print(df.iloc[3:, [0, 2]])
- 行分散取值,列切片
print(df.loc[["2019-01-04", "2019-01-06"], "C": "D"]) # 行分散取值,列切片
print(df.iloc[[3, 5], 2:])
- 行、列均分散取值
print(df.loc[["2019-01-04", "2019-01-06"], ["C", "D"]]) # 行、列均分散取值
print(df.iloc[[3, 5], [2, 3]])
11.2.4 布尔索引
print(df)
print(df > 0)
print(df[df > 0])
print(df.A > 0)
print(df[df.A > 0])
- isin()方法
df2 = df.copy()
df2['E'] = ['one', 'one', 'two', 'three', 'four', 'three']
print(df2)
ind = df2['E'].isin(["two", "four"])
print(ind)
print(df2[ind])
11.2.5 赋值
print(df)
- DataFrame 增加新列
s1 = pd.Series([1, 2, 3, 4, 5, 6], index=pd.date_range('20190101', periods=6))
print(s1)
2019-01-01 1
2019-01-02 2
2019-01-03 3
2019-01-04 4
2019-01-05 5
2019-01-06 6
Freq: D, dtype: int64
df['E'] = s1
print(df)
- 修改赋值
df.loc["2019-01-01", "A"] = 0
print(df)
df.iloc[0, 1] = 0
print(df)
df["D"] = np.array([5]*len(df)) # 可简化为df["D"] = 5
print(df)
- 修改index和columns
df.index = [i for i in range(len(df))]
df.columns = [i for i in range(df.shape[1])]
print(df)
11.3 数值运算及统计分析
11.3.1 数据的查看
dates = pd.date_range(start='2019-01-01', periods=6)
df = pd.DataFrame(np.random.randn(6, 4), index=dates, columns=["A", "B", "C", "D"])
print(df)
1. 查看前面的行
print(df.head()) # 默认5行
print(df.head(2))
2. 查看后面的行
print(df.tail()) # 默认5行
print(df.tail(3))
3. 查看总体信息
为了查看总体信息,我们先将其中一个元素改为NaN.
df.iloc[0, 3] = np.nan
print(df)
print(df.info())
11.3.2 Numpy通用函数同样适用于Pandas
1 向量化运算
x = pd.DataFrame(np.arange(4).reshape(1, 4))
print(x)
print(x + 5)
print(np.exp(x))
y = pd.DataFrame(np.arange(4, 8).reshape(1, 4))
print(x * y)
2 矩阵化运算
np.random.seed(42)
x = pd.DataFrame(np.random.randint(10, size=(10, 10)))
print(x)
- 转置
z = x.T
print(z)
- 矩阵乘法
np.random.seed(1)
y = pd.DataFrame(np.random.randint(10, size=(10, 10)))
print(x.dot(y))
我们可以通过%timeit方法来比较下两种乘法所需时间
%timeit x.dot(y)
%timeit np.dot(x, y)
可以发现np.dot(x, y)所需时间更短
- 执行相同运算,Numpy与Pandas的对比
一般来说,纯粹的计算在Numpy里执行更快
Numpy更侧重于计算,Pandas更侧重于数据分析
3 广播运算
np.random.seed(42)
x = pd.DataFrame(np.random.randint(10, size=(3, 3)), columns=list("ABC"))
print(x)
- 按行传播
print(x.iloc[0])
A 6
B 3
C 7
Name: 0, dtype: int32
print(x/x.iloc[0])
- 按列传播
print(x.div(x.A, axis=0)) # add sub div mul
在这里axis设为1,表示按列传播,也可以显式写出axis=0表示按行传播。
11.3.3 新的用法
1 索引对齐
np.random.seed(42)
A = pd.DataFrame(np.random.randint(0, 20, size=(2, 2)), columns=list("AB"))
B = pd.DataFrame(np.random.randint(0, 10, size=(3, 3)), columns=list("ABC"))
print(A)
print(B)
- Pandas会自动对齐两个对象的索引,没有的值用np.nan表示
print(A+B)
- 缺省值可用fill-value来填充
print(A.add(B, fill_value=0))
2 统计相关
- 数据种类统计
y = np.random.randint(3, size=20)
print(y)
[2 0 2 2 0 0 2 1 2 2 2 2 0 2 1 0 1 1 1 1]
print(np.unique(y))
[0 1 2]
from collections import Counter
print(Counter(y))
Counter({2: 9, 1: 6, 0: 5})
y1 = pd.DataFrame(y, columns=["A"])
print(y1)
print(np.unique(y1))
[0 1 2]
print(y1["A"].value_counts())
2 9
1 6
0 5
Name: A, dtype: int64
- 产生新的结果,并进行排序
population_dict = {"BeiJing": 2154,
"ShangHai": 2424,
"ShenZhen": 1303,
"HangZhou": 981}
population = pd.Series(population_dict)
GDP_dict = {"BeiJing": 30320,
"ShangHai": 32680,
"ShenZhen": 24222,
"HangZhou": 13468}
GDP = pd.Series(GDP_dict)
city_info = pd.DataFrame({"population": population, "GDP": GDP})
print(city_info)
city_info["per_GDP"] = city_info["GDP"]/city_info["population"]
print(city_info)
递增排序
print(city_info.sort_values(by="per_GDP"))
递减排序
print(city_info.sort_values(by="per_GDP", ascending=False))
按轴进行排序
data = pd.DataFrame(np.random.randint(20, size=(3, 4)), index=[2, 1, 0], columns=list("CBAD"))
print(data)
行排序
print(data.sort_index())
列排序
print(data.sort_index(axis=1))
- 统计方法
df = pd.DataFrame(np.random.normal(2, 4, size=(6, 4)), columns=list("ABCD"))
print(df)
非空个数
df.count()
A 6
B 6
C 6
D 6
dtype: int64
求和(默认对列求和)
df.sum()
A 13.951465
B 5.381398
C 8.792280
D 5.701582
dtype: float64
df.sum(axis=1) # 对行求和
0 18.116673
1 15.513429
2 4.575753
3 -7.834093
4 -4.075646
5 7.530610
dtype: float64
最大值 最小值
df.min() # 默认各列最小值
A -2.051324
B -5.653121
C -4.899671
D -3.698993
dtype: float64
df.max(axis=1) # 换轴后各行最大值
0 8.092119
1 8.316851
2 4.170240
3 2.967849
4 3.256989
5 7.862595
dtype: float64
print(df.idxmax()) # 最大值坐标
A 5
B 2
C 1
D 0
dtype: int64
均值
df.mean()
A 2.325244
B 0.896900
C 1.465380
D 0.950264
dtype: float64
方差
df.var()
A 11.887325
B 11.911567
C 21.841270
D 22.569365
dtype: float64
标准差
df.std()
A 3.447800
B 3.451314
C 4.673464
D 4.750723
dtype: float64
中位数
df.median()
A 2.015618
B 1.271919
C 1.208221
D -0.056035
dtype: float64
众数
data = pd.DataFrame(np.random.randint(5, size=(10, 2)), columns=list("AB"))
print(data)
data.mode()
75%分位数
df.quantile(0.75)
A 3.732105
B 2.804478
C 4.010594
D 3.836574
Name: 0.75, dtype: float64
一网打尽
df.describe()
字符类型也有describe
data_2 = pd.DataFrame([["a", "a", "c", "d"],
["c", "a", "c", "b"],
["a", "a", "d", "c"]], columns=list("ABCD"))
print(data_2)
print(data_2.describe())
相关性系数和协方差
print(df.corr())
print(df.corrwith(df["A"]))
自定义输出
apply(method)的用法:使用method的方法默认对每一列进行相应的操作
df.apply(np.cumsum)
print(df.apply(np.cumsum, axis=1))
df.apply(sum)
A 13.951465
B 5.381398
C 8.792280
D 5.701582
dtype: float64
df.apply(lambda x: x.max()-x.min())
A 9.913920
B 9.823361
C 13.216523
D 11.791112
dtype: float64
def my_describe(x):
return pd.Series([x.count(), x.mean(), x.max(), x.idxmin(), x.std()], \
index=["Count", "mean", "max", "idxmin", "std"])
print(df.apply(my_describe))
11.4 缺失值处理
11.4.1 发现缺失值
import pandas as pd
import numpy as np
data = pd.DataFrame(np.array([[1, np.nan, 2],
[np.nan, 3, 4],
[5, 6, None]]), columns=["A", "B", "C"])
print(data)
注意:有None、字符串等,数据类型全部变为object,它比int和float更消耗资源
data.dtypes
A object
B object
C object
dtype: object
data.isnull()
data.notnull()
11.4.2 删除缺失值
data = pd.DataFrame(np.array([[1, np.nan, 2, 3],
[np.nan, 4, 5, 6],
[7, 8, np.nan, 9],
[10, 11, 12, 13]]), columns=["A", "B", "C", "D"])
print(data)
注意:np.nan是一种特殊的浮点数
data.dtypes
1. 删除整行
data.dropna()
2. 删除整列
data.dropna(axis="columns")
data["D"] = np.nan
print(data)
data.dropna(axis="columns", how="all") # 所有元素均缺失时才删除,any指有缺失就删
11.4.3 填充缺失值
data.fillna(value=5)
- 用均值进行替换
fill = data.mean()
print(data.fillna(value=fill))
如果用全部平均值替代,可以先stack摊平后取平均值
fill = data.stack().mean()
print(data.fillna(value=fill))
11.5 合并数据
- 构造一个生产DataFrame的函数
def make_df(cols, ind):
"""一个简单的DataFrame"""
data = {c: [str(c)+str(i) for i in ind] for c in cols}
print(data)
return pd.DataFrame(data, ind)
make_df("ABC", range(3))
- 垂直合并
若行标签有重叠,会保留重叠行标签
df_1 = make_df("AB", [1, 2])
df_2 = make_df("AB", [3, 4])
print(df_1)
print(df_2)
print(pd.concat([df_1, df_2]))
- 水平合并
若列标签有重叠,则会保留重叠列标签
df_3 = make_df("AB", [0, 1])
df_4 = make_df("CD", [0, 1])
print(df_3)
print(df_4)
print(pd.concat([df_3, df_4], axis=1))
- 索引重叠
当标签重叠时,我们有时希望标签重新排列,则需要添加参数ignore_index=True
df_5 = make_df("AB", [1, 2])
df_6 = make_df("AB", [1, 2])
print(df_5)
print(df_6)
print(pd.concat([df_5, df_6], ignore_index=True))
列重叠同理,加上参数axis=1即可
- 对齐合并merge()
当存在对应相同的数值(共同列)时可以用merge()合并
df_9 = make_df("AB", [1, 2])
df_10 = make_df("BC", [1, 2])
print(df_9)
print(df_10)
我们可以看到B列在df_9与df_10中对应相等,我们希望合并时B列不变
print(pd.merge(df_9, df_10))
【例】合并城市信息
population_dict = {"city": ("BeiJing", "HangZhou", "ShenZhen"),
"pop": (2154, 981, 1303)}
population = pd.DataFrame(population_dict)
print(population)
GDP_dict = {"city": ("BeiJing", "ShangHai", "HangZhou"),
"GDP": (30320, 32680, 13468)}
GDP = pd.DataFrame(GDP_dict)
print(GDP)
city_info = pd.merge(population, GDP)
print(city_info)
若不想抛弃上海与深圳,则需要添加参数
city_info = pd.merge(population, GDP, how="outer")
print(city_info)
11.6 分组和数据透视表
df = pd.DataFrame({"key": ["A", "B", "C", "C", "B", "A"],
"data1": range(6),
"data2": np.random.randint(0, 10, size=6)})
print(df)
11.6.1 分组
- 延迟计算(先存起来等待处理)
df.groupby("key")
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x000001EDFF4444C0>
df.groupby("key").sum()
df.groupby("key").mean()
那么groupby到底是什么呢?
for i in df.groupby("key"):
print(str(i))
- 按列取值
df.groupby("key")["data2"].sum()
key
A 15
B 9
C 11
Name: data2, dtype: int32
- 按组迭代
for data, group in df.groupby("key"):
print("{0:5} shape={1}".format(data, group.shape))
- 调用方法
df.groupby("key")["data1"].describe()
- 支持更复杂的操作
df.groupby("key").aggregate(["min", "median", "max"])
- 过滤
np.random.seed(1)
df = pd.DataFrame({"key": ["A", "B", "C", "C", "B", "A"],
"data1": range(6),
"data2": np.random.randint(0, 10, size=6)})
print(df)
def filter_func(x):
return x["data2"].std() > 3
print(df.groupby("key")["data2"].std())
print(df.groupby("key").filter(filter_func))
- 转换
df = pd.DataFrame({"key": ["A", "B", "C", "C", "B", "A"],
"data1": range(6),
"data2": np.random.randint(0, 10, size=6)})
print(df)
print(df.groupby("key").transform(lambda x: x - x.mean()))
- apply方法
def norm_by_data2(x):
x["data1"] /= x["data2"].sum()
return x
print(df.groupby("key").apply(norm_by_data2))
- 将列表、数组设为分组键
print(df)
L = [0, 1, 0, 1, 2, 0]
print(df.groupby(L).sum())
- 用字典将索引映射到分组
df2 = df.set_index("key")
print(df2)
mapping = {"A": "first", "B": "constant", "C": "constant"}
print(df2.groupby(mapping).sum())
- 任意Python函数
print(df2.groupby(str.lower).mean())
- 多个有效值组成的列表
print(df2.groupby([str.lower, mapping]).mean())
【例1】行星观测数据处理
import seaborn as sns
planets = sns.load_dataset('planets')
print(planets.shape) # 获取形状
print(planets.head()) # 查看前五行
print(planets.describe()) # 统计信息
现在我们希望通过分组实现不同观测方法(method)下不同时代(decade,十年为单位)的观测数量。
首先,我们应该定义时代(decade)。
decade = 10 * (planets["year"]//10)
print(decade.head())
decade = decade.astype(str) + "s"
decade.name = "decade"
print(decade.head())
定义好之后,我们对method,decade进行分组。
print(planets.groupby(["method", decade]).sum())
实际上,我们只需要number这一列数据,所以我们可以把number单独提出来,然后利用unstack展开使其更美观,最后用fillna将缺失值填充为0即可。
print(planets.groupby(["method", decade])["number"].sum().unstack().fillna(0))
11.6.2 数据透视表
【例2】泰坦尼克号乘客数据分析
import seaborn as sns
titanic = sns.load_dataset("titanic")
print(titanic.head())
print(titanic.describe())
现在我们想得到不同性别的生存率。
print(titanic.groupby("sex")["survived"].mean())
sex
female 0.742038
male 0.188908
Name: survived, dtype: float64
索引"servived"用一个中括号的表示形式是Series,而两个中括号则是DataFrame.
print(titanic.groupby("sex")[["survived"]].mean())
更具体地,我们想看到不同性别下不同舱的生存情况。
print(titanic.groupby(["sex", "class"])["survived"].aggregate("mean").unstack())
我们发现单凭groupby写起来也比较复杂,可读性不佳,但Pandas里面提供了一种数据透视表的方法。我们一起看一下,如何用数据透视表实现相同功能。
print(titanic.pivot_table("survived", index="sex", columns="class"))
我们可以发现直接用pivot_table方法默认返回数据平均值。
我们也可以添加其他参数,来得到不同的结果。
aggfunc来更改方法,margins来设置总览。
print(titanic.pivot_table("survived", index="sex", columns="class", aggfunc="mean", margins=True))
当我们利用pivot_table来处理数据时,希望处理多类数据,可在aggfuc中分别选择对应方法。比如该例中我们不仅想得到生存个数,还需要票价均值。
print(titanic.pivot_table(index="sex", columns="class", aggfunc={"survived": "sum", "fare": "mean"}))
11.7 其他
- 向量化字符串操作
- 处理时间序列
- 多级索引:用于多维数组
base_data = np.array([[1771, 11115],
[2154, 30320],
[2141, 13070],
[2424, 32680],
[1077, 7806],
[1303, 24222],
[798, 4789],
[981, 13486]])
data = pd.DataFrame(base_data, index=[
["BeiJing", "BeiJing", "ShangHai", "ShangHai", "ShenZhen", "ShenZhen", "HangZhou", "HangZhou"],
[2008, 2018] * 4], columns=["population", "GDP"])
print(data)
修改行索引名称
data.index.names = ["city", "year"]
print(data)
列数据的取值
print(data["GDP"])
取值某个城市GDP
print(data.loc["ShangHai", "GDP"])
取值某个城市某年情况
print(data.loc["ShangHai", 2018])
- 高性能的Pandas:eval()
df1, df2, df3, df4 = (pd.DataFrame(np.random.random((10000,100))) for i in range(4))
%timeit (df1+df2)/(df3+df4)
17.6 ms ± 120 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
- 减少了复合代数式计算中间过程的内存分配,运行速度有所改善
%timeit pd.eval("(df1+df2)/(df3+df4)")
10.5 ms ± 153 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
可以比较下运算结果是相同的
np.allclose((df1+df2)/(df3+df4), pd.eval("(df1+df2)/(df3+df4)"))
True
- 实现列间运算
df = pd.DataFrame(np.random.random((1000, 3)), columns=list("ABC"))
df.head()
df["D"] = pd.eval("(df.A+df.B)/(df.C-1)")
df.head()
- 使用局部变量
column_mean = df.mean(axis=1)
res = df.eval("A+@column_mean")
res.head()
- 高性能的Pandas:query()
df.head()
%timeit df[(df.A < 0.5) & (df.B > 0.5)]
1.11 ms ± 9.38 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit df.query("(A < 0.5)&(B > 0.5)")
2.55 ms ± 199 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
时间反而变长了,究其原因,是因为数据量过小,导致调用该方法本身的时间成本过高
- eval()与query()使用时机
小数组时,普通方法反而更快
因此,在数据量较大的情况下,再调用eval与query来提升运行速度
df.values.nbytes
32000
df1.values.nbytes
8000000
以上,便是第十一节深入探索内容,Pandas是一个更侧重于数据分析的高级工具。
下一节将深入理解Matplotlib库。