跳转至

Pandas核心语法[3]

“DataFrame 是 Pandas 的核心数据结构,支持多种数据类型和灵活的操作方式。无论是嵌套字典、NumPy 数组还是 CSV 文件,都可以轻松转换为 DataFrame,助你快速完成数据分析任务。”


1. 快速探索 DataFrame

1.1. 创建 DataFrame

DataFrame 含有一组有序且有命名的列,每一列可以是不同的数据类型(数值、字符串、布尔值等)。DataFrame 既有行索引也有列索引,可以看作由共用同一个索引的Series组成的字典。虽然DataFrame是二维的,但利用层次化索引,仍然可以用其表示更高维度的表格型数据。如果你使用的是Jupyter notebook,pandas的DataFrame 对象将会展示为对浏览器更为友好的HTML表格。

1.1.1. 传入一个由等长列表或Numpy数组构成的字典

1
2
3
4
5
6
import pandas as pd
data = {"state":["Ohio","Ohio","Ohio","Nevada","Nevada","Nevada"],
       "year":[2000,2001,2002,2003,2004,2005],
       "pop":[1.5,1.7,3.6,2.4,2.9,3.2]}
frame = pd.DataFrame(data)
frame

50%

生成的DataFrame会自动加上索引(和Series一样),且全部列会按照data键(键的顺序取决于在字典中插入的顺序)的顺序有序排列。 (如果你使用的是Jupyter notebook,pandas的DataFrame对象会展示为对浏览器更为友好的HTML表格)


对于特别大的DataFrame,可以使用head方法,只展示前5行。相似地,tail方法会返回最后5行。

1
2
print(frame.head())
print(frame.tail())

50%

下面还有几种创建DataFrame的情况:

1
2
3
4
5
# 如果指定了列的顺序,则DataFrame的列就会按照指定顺序进行排列
frame1 = pd.DataFrame(data=data,columns=["year","state","pop"])

# 如果字典中不包括传入的列,就会在结果中产生缺失值
frame2 = pd.DataFrame(data=data,columns=["year","state","pop","debt"])

1.1.2. 传入嵌套字典

如果将嵌套字典传给DataFrame,pandas就会将外层字典的键解释为列,将内层字典的键解释为行索引。

1
2
3
populations = {"Ohio":{2000:1.5,2001:1.7,2002:3.6},"Nevada":{2001:2.4,2002:2.9}}
frame3 = pd.DataFrame(populations)
frame3

50%

使用类似于Numpy数组的方法,可以对 DataFrame 进行转置(交换行和列):

1
frame3.T

50%

内层字典的键被合并后形成了结果的索引。如果明确指定了索引,则不会这样:


1
pd.DataFrame(populations,index=["2001","2002","2003"])

50%

由Series组成的字典差不多也是一样的用法:

1
2
pdata = {"Ohio":frame3["Ohio"][:-1],"Nevada":frame3["Nevada"][:2]}
pd.DataFrame(pdata)

50%

可以向DataFrame构造器输入的数据:


类型 说明
字典 (Dict) 键为列名,值为列表、NumPy 数组或 Series。每列的长度必须一致。
列表 (List) 列表中的每个元素是一个字典,字典的键为列名,值为对应列的数据。
NumPy 数组 二维数组,每行对应 DataFrame 的一行,每列对应 DataFrame 的一列。
Series 单个 Series 可以构造单列的 DataFrame,多个 Series 可以构造多列。
结构化数组 NumPy 的结构化数组,字段名对应 DataFrame 的列名。
其他 DataFrame 可以通过复制另一个 DataFrame 来创建新的 DataFrame。
CSV 文件 通过 pd.read_csv() 读取 CSV 文件并转换为 DataFrame。
Excel 文件 通过 pd.read_excel() 读取 Excel 文件并转换为 DataFrame。
JSON 数据 通过 pd.read_json() 读取 JSON 数据并转换为 DataFrame。
SQL 查询结果 通过 pd.read_sql() 读取 SQL 查询结果并转换为 DataFrame。
HTML 表格 通过 pd.read_html() 从 HTML 页面中提取表格并转换为 DataFrame。
剪贴板数据 通过 pd.read_clipboard() 从剪贴板中读取数据并转换为 DataFrame。

如果设置了DataFrame的index和columns的name属性,则这些信息也会显示出来:

1
2
3
frame3.index.name = "year"
frame3.columns.name = "state"
frame3

50%

1
2
3
4
5
# 二维的ndarray的DataFrame形式返回
frame3.to_numpy()

# 如果DataFrame各列的数据类型不同,则返回数组会选用能兼容所有列的数据类型:
frame2.to_numpy()

50%

1.2. DataFrame 的合并和连接

在 Pandas 中,concat、join 和 merge 是用于合并和连接 DataFrame 的三种主要方法。它们各有不同的用途和适用场景,以下是详细说明。


1.2.1. ​concat:基于轴的数据拼接

concat 主要用于沿指定轴(行或列)将多个 DataFrame 或 Series 拼接在一起。

参数说明: - ​objs:需要拼接的 DataFrame 或 Series 列表。 - ​axis:拼接方向,0 表示按行拼接(默认),1 表示按列拼接。 - join:拼接方式,'outer'(默认,保留所有索引)或 'inner'(仅保留共同索引)。 - ignore_index:是否忽略原索引并生成新索引,默认为 False。 - keys:为拼接后的数据添加层次化索引。

示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import pandas as pd

df1 = pd.DataFrame({'A': [1, 2], 'B': [3, 4]})
df2 = pd.DataFrame({'A': [5, 6], 'B': [7, 8]})

# 按行拼接
result = pd.concat([df1, df2], axis=0)
print(result)

# 按列拼接
result = pd.concat([df1, df2], axis=1)
print(result)

适用场景: - 将多个结构相似的数据集简单堆叠在一起。 - 不需要基于键值匹配,只需按行或列拼接。


1.2.2. merge:基于键值的合并

merge 用于根据一个或多个键将两个 DataFrame 合并在一起,类似于 SQL 中的 JOIN 操作。

参数说明: - ​left:左侧的 DataFrame。 - right:右侧的 DataFrame。 - ​how:合并方式,可选 'inner'(默认,内连接)、'left'(左连接)、'right'(右连接)、'outer'(外连接)。 - ​on:用于合并的列名(键),必须在两个 DataFrame 中都存在。 - left_on/right_on:当两个 DataFrame 的键列名不同时,分别指定左侧和右侧的键列。 - suffixes:当两个 DataFrame 中存在重复列名时,用于区分的后缀。

示例:

1
2
3
4
5
6
7
8
9
df1 = pd.DataFrame({'key': ['A', 'B', 'C'], 'value1': [1, 2, 3]})
df2 = pd.DataFrame({'key': ['B', 'C', 'D'], 'value2': [4, 5, 6]})

# 内连接
result = pd.merge(df1, df2, on='key', how='inner')
print(result)
# 外连接
result = pd.merge(df1, df2, on='key', how='outer')
print(result)

适用场景: - 需要根据某些列(键)将两个表关联。 - 类似于 SQL 中的 JOIN,适合处理结构化数据。


1.2.3. join:基于索引的合并

join 是基于索引将两个 DataFrame 合并在一起,是 merge 的简化版。 参数说明: - other:要连接的另一个 DataFrame。 - ​on:用于连接的列名或索引。 - ​how:连接方式,可选 'left'(默认,左连接)、'right'(右连接)、'outer'(外连接)、'inner'(内连接)。 - ​lsuffix/rsuffix:当两个 DataFrame 中存在重复列名时,分别指定左侧和右侧的后缀。

示例:

1
2
3
4
5
6
df1 = pd.DataFrame({'A': [1, 2], 'B': [3, 4]}, index=['x', 'y'])
df2 = pd.DataFrame({'C': [5, 6], 'D': [7, 8]}, index=['x', 'y'])

# 基于索引的左连接
result = df1.join(df2, how='left')
print(result)

适用场景: - 基于索引进行简单的数据合并。 - 适合处理索引对齐的数据。

方法 主要用途 适用场景 灵活性 性能
concat 基于轴的数据拼接 简单堆叠数据,结构相似的数据集 按行或列拼接 适合大规模数据
merge 基于键值的合并,类似于 SQL 的 JOIN 结构化数据,需要关联表 支持多种连接方式 适合小规模数据
join 基于索引的合并 索引对齐的数据 简化版 merge 适合简单操作

1.3. 删除行和列

关键字del可以像在字典中那样删除列。

1
2
3
4
5
frame2["eastern"] = frame2["state"] = "ohio"
print(frame2)

del frame2["eastern"]
print(frame2.columns)

50%

1.1.4. 定位、读取和修改

1.1.4.1. 获取列

通过类似于字典标记或点属性的方式,可以将DataFrame的列获取为一个Series。

1
2
print(frame2["state"])
print(frame2.year)

50%

如果列名包含空格或下划线以外的符号,是不能用点属性的方式访问的。

1.1.4.2. 修改列

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import numpy as np
# 通过赋值的方法修改列
frame2["debt"] = 16.5
print(frame2)
frame2["debt"] = np.arange(6.)
print(frame2)

# 将列表和数组赋值给某个列
val = pd.Series([1.2,-1.5,-1.7],index=["two","four","five"])  # 长度必须与DataFrame保持一致
frame2["debt"] = val
print(frame2)

50%


1.1.4.2. 获取行(iloc和loc)

通过ilocloc属性,也可以通过位置或名称的方式进行获取行。

1
2
print(frame2.loc[1])
print(frame2.iloc[2])

50%

1.1.5. 转置

转置操作是将 DataFrame 的行和列进行互换,即将行变为列,列变为行。Pandas 提供了两种方法来实现转置: - T 属性:直接调用 DataFrame.T 进行转置。 - ​transpose() 方法:通过 DataFrame.transpose() 实现转置。


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import pandas as pd

# 创建一个示例 DataFrame
data = {'Name': ['Tom', 'Jack', 'Steve'], 'Age': [28, 34, 29], 
        'City': ['London', 'New York', 'Sydney']}
df = pd.DataFrame(data)

# 使用 T 属性转置
transposed_df = df.T
print(transposed_df)

# 使用 transpose() 方法转置
transposed_df = df.transpose()
print(transposed_df)

注意事项: - 转置操作会改变 DataFrame 的结构,但不会修改原始数据。 - 如果 DataFrame 包含混合数据类型,转置后可能需要重新调整数据类型。

1.1.6. 重采样(resample)

重采样是将时间序列数据从一个频率转换为另一个频率的过程。Pandas 提供了 resample() 方法来实现重采样,支持以下两种类型: - ​上采样(Upsampling)​:将低频数据转换为高频数据(如将日数据转换为小时数据)。 - ​下采样(Downsampling)​:将高频数据转换为低频数据(如将分钟数据转换为小时数据)。


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import pandas as pd

# 创建一个示例时间序列 DataFrame
data = {'date': pd.date_range(start='1/1/2020', periods=100, freq='D'),
        'price': range(100)}
df = pd.DataFrame(data)
df.set_index('date', inplace=True)

# 下采样:将日数据转换为月数据,并计算每月的平均价格
monthly_avg_price = df['price'].resample('M').mean()
print(monthly_avg_price)

# 上采样:将日数据转换为小时数据,并使用前向填充
hourly_price = df['price'].resample('H').ffill()
print(hourly_price)

注意事项: - 重采样需要 DataFrame 的索引为时间类型。 - 可以使用 fillna()interpolate() 方法处理缺失值。