pandas 快速入门#
这是 pandas 的一个简短介绍,主要面向新用户。你可以在实用代码片段中查看更复杂的示例。
通常,我们按如下方式导入
1 | In [1]: import numpy as np |
pandas 中的基本数据结构#
Pandas 提供了两种用于处理数据的类
对象创建#
请参阅数据结构简介部分。
通过传入值列表创建Series
,让 pandas 创建默认的RangeIndex
。
1 | In [3]: s = pd.Series([1, 3, 5, np.nan, 6, 8]) |
通过传入 NumPy 数组,使用date_range()
创建带有日期时间索引和标签列的DataFrame
1 | In [5]: dates = pd.date_range("20130101", periods=6) |
通过传入一个对象字典创建DataFrame
,其中键是列标签,值是列值。
1 | In [9]: df2 = pd.DataFrame( |
1 | In [11]: df2.dtypes |
如果你使用 IPython,列名(以及公共属性)的 Tab 自动补全功能会自动启用。以下是部分将自动补全的属性:
1 | In [12]: df2.<TAB> # noqa: E225, E999 |
如你所见,列 A
、B
、C
和 D
会自动 Tab 补全。E
和 F
也在其中;其余属性为简洁起见已被截断。
查看数据#
请参阅基本核心功能部分。
使用DataFrame.head()
和DataFrame.tail()
分别查看框架的顶部和底部行。
1 | In [13]: df.head() |
显示DataFrame.index
或DataFrame.columns
1 | In [15]: df.index |
使用DataFrame.to_numpy()
返回底层数据的 NumPy 表示,不包含索引或列标签。
1 | In [17]: df.to_numpy() |
注意
NumPy 数组的整个数组只有一个 dtype,而 pandas DataFrames 的每列有一个 dtype。当你调用DataFrame.to_numpy()
时,pandas 会找到能够容纳 DataFrame 中 所有 dtypes 的 NumPy dtype。如果共同的数据类型是 object
,则DataFrame.to_numpy()
将需要复制数据。
1 | In [18]: df2.dtypes |
describe()
显示数据的快速统计摘要
1 | In [20]: df.describe() |
转置数据
1 | In [21]: df.T |
1 | In [22]: df.sort_index(axis=1, ascending=False) |
1 | In [23]: df.sort_values(by="B") |
选择#
请参阅索引文档索引与选择数据和MultiIndex / 高级索引。
Getitem ([]
)#
对于DataFrame
,传入单个标签会选择一列并生成一个Series
,等同于 df.A
1 | In [24]: df["A"] |
对于DataFrame
,传入切片 :
会选择匹配的行。
1 | In [25]: df[0:3] |
按标签选择#
更多信息请参阅按标签选择,使用DataFrame.loc()
或DataFrame.at()
。
选择与标签匹配的行
1 | In [27]: df.loc[dates[0]] |
选择所有行 (:
) 和选定的列标签
1 | In [28]: df.loc[:, ["A", "B"]] |
对于标签切片,两个端点都包含在内
1 | In [29]: df.loc["20130102":"20130104", ["A", "B"]] |
选择单个行和列标签会返回一个标量
1 | In [30]: df.loc[dates[0], "A"] |
为了快速访问标量(等同于之前的方法)
1 | In [31]: df.at[dates[0], "A"] |
按位置选择#
更多信息请参阅按位置选择,使用DataFrame.iloc()
或DataFrame.iat()
。
通过传入整数的位置进行选择
1 | In [32]: df.iloc[3] |
整数切片行为类似于 NumPy/Python
1 | In [33]: df.iloc[3:5, 0:2] |
整数位置列表
1 | In [34]: df.iloc[[1, 2, 4], [0, 2]] |
显式切片行
1 | In [35]: df.iloc[1:3, :] |
显式切片列
1 | In [36]: df.iloc[:, 1:3] |
显式获取值
1 | In [37]: df.iloc[1, 1] |
为了快速访问标量(等同于之前的方法)
1 | In [38]: df.iat[1, 1] |
布尔索引#
选择 df.A
大于 0
的行。
1 | In [39]: df[df["A"] > 0] |
从满足布尔条件的DataFrame
中选择值
1 | In [40]: df[df > 0] |
使用isin()
方法进行过滤
1 | In [41]: df2 = df.copy() |
设置#
设置新列会自动按索引对齐数据
1 | In [45]: s1 = pd.Series([1, 2, 3, 4, 5, 6], index=pd.date_range("20130102", periods=6)) |
按标签设置值
1 | In [48]: df.at[dates[0], "A"] = 0 |
按位置设置值
1 | In [49]: df.iat[0, 1] = 0 |
通过分配 NumPy 数组进行设置
1 | In [50]: df.loc[:, "D"] = np.array([5] * len(df)) |
先前的设置操作的结果
1 | In [51]: df |
带设置的 where
操作
1 | In [52]: df2 = df.copy() |
缺失数据#
对于 NumPy 数据类型,np.nan
表示缺失数据。默认情况下,它不包含在计算中。请参阅缺失数据部分。
重新索引允许你更改/添加/删除指定轴上的索引。这会返回数据的副本。
1 | In [55]: df1 = df.reindex(index=dates[0:4], columns=list(df.columns) + ["E"]) |
DataFrame.dropna()
删除任何包含缺失数据的行
1 | In [58]: df1.dropna(how="any") |
DataFrame.fillna()
填充缺失数据
1 | In [59]: df1.fillna(value=5) |
isna()
获取值为 nan
的布尔掩码
1 | In [60]: pd.isna(df1) |
操作#
请参阅二元运算基本部分。
统计#
操作通常排除缺失数据。
计算每列的平均值
1 | In [61]: df.mean() |
计算每行的平均值
1 | In [62]: df.mean(axis=1) |
与具有不同索引或列的另一个Series
或DataFrame
进行操作时,结果将与索引或列标签的并集对齐。此外,pandas 会沿指定维度自动广播,并将未对齐的标签填充为np.nan
。
1 | In [63]: s = pd.Series([1, 3, 5, np.nan, 6, 8], index=dates).shift(2) |
用户定义函数#
DataFrame.agg()
和DataFrame.transform()
分别应用一个用户定义函数,该函数会减少或广播其结果。
1 | In [66]: df.agg(lambda x: np.mean(x) * 5.6) |
值计数#
更多信息请参阅直方图和离散化。
1 | In [68]: s = pd.Series(np.random.randint(0, 7, size=10)) |
字符串方法#
Series
在 str
属性中配备了一组字符串处理方法,可以轻松地对数组的每个元素进行操作,如下面的代码片段所示。更多信息请参阅矢量化字符串方法。
1 | In [71]: s = pd.Series(["A", "B", "C", "Aaba", "Baca", np.nan, "CABA", "dog", "cat"]) |
合并#
拼接#
pandas 提供了各种功能,可以轻松地将 Series
和 DataFrame
对象与各种集合逻辑(用于索引)和关系代数功能(用于连接/合并类型操作)结合在一起。
请参阅合并部分。
使用concat()
按行拼接 pandas 对象
1 | In [73]: df = pd.DataFrame(np.random.randn(10, 4)) |
连接#
merge()
支持沿着特定列进行 SQL 风格的连接。请参阅数据库风格连接部分。
1 | In [77]: left = pd.DataFrame({"key": ["foo", "foo"], "lval": [1, 2]}) |
merge()
基于唯一键进行合并
1 | In [82]: left = pd.DataFrame({"key": ["foo", "bar"], "lval": [1, 2]}) |
分组#
“分组”指的是一个或多个以下步骤的过程
-
根据某些条件将数据分拆成组
-
对每个组独立地应用一个函数
-
将结果组合成一个数据结构
请参阅分组部分。
1 | In [87]: df = pd.DataFrame( |
按列标签分组,选择列标签,然后将DataFrameGroupBy.sum()
函数应用于结果组
1 | In [89]: df.groupby("A")[["C", "D"]].sum() |
按多列标签分组会形成MultiIndex
。
1 | In [90]: df.groupby(["A", "B"]).sum() |
重塑#
堆叠#
1 | In [91]: arrays = [ |
stack()
方法“压缩”了 DataFrame 列中的一个层
1 | In [96]: stacked = df2.stack(future_stack=True) |
对于一个“堆叠”的 DataFrame 或 Series(其 index
为 MultiIndex
),stack()
的逆操作是 unstack()
,它默认会解除堆叠最底层
1 | In [98]: stacked.unstack() |
透视表#
请参阅透视表部分。
1 | In [101]: df = pd.DataFrame( |
pivot_table()
通过指定values
、index
和columns
来透视DataFrame
1 | In [103]: pd.pivot_table(df, values="D", index=["A", "B"], columns=["C"]) |
时间序列#
pandas 具有简单、强大且高效的功能,用于在频率转换期间执行重采样操作(例如,将秒级数据转换为 5 分钟级数据)。这在金融应用中非常常见,但不仅限于此。请参阅时间序列部分。
1 | In [104]: rng = pd.date_range("1/1/2012", periods=100, freq="s") |
Series.tz_localize()
将时间序列本地化到某个时区
1 | In [107]: rng = pd.date_range("3/6/2012 00:00", periods=5, freq="D") |
Series.tz_convert()
将时区感知的时间序列转换为另一个时区
1 | In [112]: ts_utc.tz_convert("US/Eastern") |
向时间序列添加非固定时长(BusinessDay
)
1 | In [113]: rng |
分类数据#
pandas 可以在DataFrame
中包含分类数据。有关完整文档,请参阅分类简介和API 文档。
1 | In [115]: df = pd.DataFrame( |
将原始等级转换为分类数据类型
1 | In [116]: df["grade"] = df["raw_grade"].astype("category") |
将类别重命名为更有意义的名称
1 | In [118]: new_categories = ["very good", "good", "very bad"] |
重新排序类别并同时添加缺失的类别(Series.cat()
下的方法默认返回一个新的Series
)
1 | In [120]: df["grade"] = df["grade"].cat.set_categories( |
排序是按类别顺序,而不是字典顺序
1 | In [122]: df.sort_values(by="grade") |
使用 observed=False
按分类列分组也会显示空类别
1 | In [123]: df.groupby("grade", observed=False).size() |
绘图#
请参阅绘图文档。
我们使用标准约定来引用 matplotlib API
1 | In [124]: import matplotlib.pyplot as plt |
plt.close
方法用于关闭图形窗口
1 | In [126]: ts = pd.Series(np.random.randn(1000), index=pd.date_range("1/1/2000", periods=1000)) |
plot()
绘制所有列
1 | In [129]: df = pd.DataFrame( |
导入和导出数据#
请参阅IO 工具部分。
CSV#
写入 CSV 文件:使用DataFrame.to_csv()
1 | In [134]: df = pd.DataFrame(np.random.randint(0, 5, (10, 5))) |
1 | In [136]: pd.read_csv("foo.csv") |
Parquet#
写入 Parquet 文件
1 | In [137]: df.to_parquet("foo.parquet") |
使用read_parquet()
从 Parquet 文件读取
1 | In [138]: pd.read_parquet("foo.parquet") |
Excel#
读写Excel。
使用DataFrame.to_excel()
写入 Excel 文件
1 | In [139]: df.to_excel("foo.xlsx", sheet_name="Sheet1") |
使用read_excel()
从 Excel 文件读取
1 | In [140]: pd.read_excel("foo.xlsx", "Sheet1", index_col=None, na_values=["NA"]) |
常见陷阱#
如果您尝试对Series
或DataFrame
执行布尔操作,可能会看到类似以下的异常:
1 | In [141]: if pd.Series([False, True, False]): |