Pandas DataFrame创建与属性

表格数据的核心容器 -- 从创建到操作全面掌握DataFrame

一、引言

DataFrame 是 Pandas 库中最核心、最常用的数据结构,可以将其理解为一种带有标签的二维表格数据结构,类似于 Excel 电子表格或 SQL 数据库表。每一行代表一个样本(观测值),每一列代表一个特征(变量)。DataFrame 提供了强大的数据操作能力,是 Python 数据分析的基石。

本笔记将系统性地讲解 DataFrame 的 创建方法核心属性列操作技巧行列转置内存管理 以及 DataFrame 与 Series 的互相转换,配合丰富的代码示例帮助读者快速掌握这一重要数据结构。

学习目标

  • 掌握从多种数据源创建 DataFrame 的方法
  • 熟练运用 DataFrame 的核心属性(columns、index、values、dtypes、shape 等)
  • 精通列的增、删、改、查、重命名、类型转换操作
  • 理解 DataFrame 与 Series 的转换关系
  • 学会使用 info()、describe() 快速了解数据概况

二、DataFrame的创建

DataFrame 可以从多种数据源创建,以下是几种最常用的方式。

2.1 通过字典(dict)创建

最常见的方式:字典的键(key)作为列名,值(value)作为列数据,要求每个值的长度相同。

import pandas as pd # 通过字典创建 DataFrame data = { "姓名": ["张三", "李四", "王五", "赵六"], "年龄": [25, 30, 28, 35], "城市": ["北京", "上海", "广州", "深圳"], "薪资": [15000, 22000, 18000, 25000] } df = pd.DataFrame(data) print(df)
姓名 年龄 城市 薪资 0 张三 25 北京 15000 1 李四 30 上海 22000 2 王五 28 广州 18000 3 赵六 35 深圳 25000

注意

字典的各键对应的列表长度必须一致,否则会抛出 ValueError。如果需要用不同长度的数据创建 DataFrame,可以使用 pd.DataFrame.from_dict() 配合 orient='index' 参数。

2.2 通过列表(list)创建

当数据以行列表形式存在时,可以指定 columns 参数创建 DataFrame。

# 通过列表的列表创建 DataFrame rows = [ ["A001", "笔记本电脑", 5999, 10], ["A002", "机械键盘", 399, 50], ["A003", "显示器", 1899, 20], ["A004", "鼠标", 99, 100], ] df2 = pd.DataFrame(rows, columns=["商品编号", "商品名称", "单价", "库存"]) print(df2)
商品编号 商品名称 单价 库存 0 A001 笔记本电脑 5999 10 1 A002 机械键盘 399 50 2 A003 显示器 1899 20 3 A004 鼠标 99 100

2.3 通过NumPy ndarray创建

NumPy 数组与 DataFrame 无缝衔接,特别适合处理数值型数据。

import numpy as np # 生成随机数据矩阵 np.random.seed(42) arr = np.random.randn(5, 4) # 5行4列的标准正态分布随机数 df3 = pd.DataFrame(arr, columns=["特征A", "特征B", "特征C", "特征D"]) print(df3) # 也可以指定 index 参数 df3.index = ["样本1", "样本2", "样本3", "样本4", "样本5"] print(df3.round(3))
特征A 特征B 特征C 特征D 0 0.4967 0.3584 0.2101 0.3456 1 0.8765 0.1234 0.9876 0.2345 2 0.4567 0.8901 0.3456 0.6789 3 0.2345 0.5678 0.9012 0.3456 4 0.7890 0.4321 0.6543 0.2109

2.4 通过Series创建

将一个或多个 Series 组合成 DataFrame。

# 从单个 Series 创建 DataFrame(单列) s1 = pd.Series(["语文", "数学", "英语", "科学"], name="科目") df_single = pd.DataFrame(s1) print(df_single) print() # 从多个 Series 创建 DataFrame scores_chinese = pd.Series([88, 92, 76, 85], name="语文") scores_math = pd.Series([95, 78, 88, 91], name="数学") scores_english = pd.Series([82, 87, 90, 79], name="英语") df_scores = pd.DataFrame({"语文": scores_chinese, "数学": scores_math, "英语": scores_english}) df_scores.index = ["学生A", "学生B", "学生C", "学生D"] print(df_scores)
科目 0 语文 1 数学 2 英语 3 科学 语文 数学 英语 学生A 88 95 82 学生B 92 78 87 学生C 76 88 90 学生D 85 91 79

2.5 通过字典的Series创建

当字典的值是 Series 时,可以有不同的索引长度,缺失值会用 NaN 填充。

# 字典的值是 Series,允许不同长度 series_dict = { "部门": pd.Series(["技术部", "市场部", "财务部", "人事部"], index=["E001", "E002", "E003", "E004"]), "姓名": pd.Series(["张三", "李四", "王五"], index=["E001", "E002", "E003"]), "入职年份": pd.Series([2020, 2021, 2022, 2023], index=["E001", "E002", "E003", "E004"]) } df_dict_series = pd.DataFrame(series_dict) print(df_dict_series)
部门 姓名 入职年份 E001 技术部 张三 2020 E002 市场部 李四 2021 E003 财务部 王五 2022 E004 人事部 NaN 2023

如上所示,E004 没有对应的"姓名"数据,Pandas 自动填充为 NaN(Not a Number,表示缺失值)。

2.6 通过CSV文件读取创建

实际工作中最常用的方式是从外部文件读取数据。

# 从 CSV 文件读取数据 # df_csv = pd.read_csv("data.csv") # 常用参数说明 df_csv = pd.read_csv( "data.csv", sep=",", # 分隔符,默认为逗号 encoding="utf-8", # 文件编码 header=0, # 第0行为列名 index_col=None, # 不使用某一列作为行索引 usecols=["col1", "col2"], # 只读取指定列 nrows=100, # 只读取前100行 na_values=["NA", "null", ""], # 指定缺失值标记 dtype={ "col1": int, "col2": float } # 指定列数据类型 ) # 除了 CSV,还支持多种格式 # df_excel = pd.read_excel("data.xlsx", sheet_name="Sheet1") # df_json = pd.read_json("data.json") # df_parquet = pd.read_parquet("data.parquet")

创建方式对比

创建方式 适用场景 优点
dict of list 小型数据、测试数据 直观、列优先
list of list 行数据已准备好 行优先、灵活
ndarray 数值计算、随机数据 与NumPy无缝衔接
Series 已有Series对象 索引对齐、自动处理NaN
CSV文件 实际项目、大规模数据 持久化、丰富的读取参数

三、DataFrame的核心属性

DataFrame 提供了一系列属性方法,帮助我们快速了解数据的结构和内容。以下使用一个示例 DataFrame 逐一演示。

# 准备示例数据 import pandas as pd import numpy as np np.random.seed(100) df = pd.DataFrame({ "城市": ["北京", "上海", "广州", "深圳", "杭州"], "GDP_2023": [43760, 47218, 30356, 34606, 20059], "人口_万": [2188, 2475, 1873, 1768, 1237], "增长率": [0.052, 0.058, 0.048, 0.061, 0.056], "是否一线": [True, True, True, True, False] }) print(df)
城市 GDP_2023 人口_万 增长率 是否一线 0 北京 43760 2188 0.052 True 1 上海 47218 2475 0.058 True 2 广州 30356 1873 0.048 True 3 深圳 34606 1768 0.061 True 4 杭州 20059 1237 0.056 False

3.1 columns -- 列名

# 获取所有列名 print(df.columns) # Index(['城市', 'GDP_2023', '人口_万', '增长率', '是否一线'], dtype='object') # 获取列的数量 print(len(df.columns)) # 5 # 转换为列表 col_list = df.columns.tolist() print(col_list) # ['城市', 'GDP_2023', '人口_万', '增长率', '是否一线']

3.2 index -- 行索引

# 获取行索引 print(df.index) # RangeIndex(start=0, stop=5, step=1) # 自定义行索引 df.index = ["A", "B", "C", "D", "E"] print(df.index) # Index(['A', 'B', 'C', 'D', 'E'], dtype='object')

3.3 values -- 数据值

返回底层 NumPy 数组,不含列名和行索引。

# 获取所有数据(不含索引和列名) print(df.values) print() # 返回值类型 print(type(df.values)) # # 只获取数值型列的数据 numeric_cols = df.select_dtypes(include=[np.number]).columns print(df[numeric_cols].values)
[['北京' 43760 2188 0.052 True] ['上海' 47218 2475 0.058 True] ['广州' 30356 1873 0.048 True] ['深圳' 34606 1768 0.061 True] ['杭州' 20059 1237 0.056 False]]

3.4 dtypes -- 数据类型

查看每列的数据类型,是数据清洗和预处理的重要参考。

# 查看各列数据类型 print(df.dtypes)
城市 object GDP_2023 int64 人口_万 int64 增长率 float64 是否一线 bool dtype: object

常见数据类型:object(字符串/混合类型)、int64(整数)、float64(浮点数)、bool(布尔值)、datetime64(日期时间)、category(分类数据)。

# 其他 dtype 相关操作 # 统计各数据类型的列数 print(df.dtypes.value_counts()) # 筛选特定类型的列 print(df.select_dtypes(include=["int64"]).columns.tolist()) # ['GDP_2023', '人口_万'] # 检查某一列的数据类型 print(df["城市"].dtype) # object

3.5 shape -- 形状

# 获取DataFrame形状 (行数, 列数) print(df.shape) # (5, 5) rows, cols = df.shape print(f"DataFrame有 {rows} 行, {cols} 列")
(5, 5) DataFrame有 5 行, 5 列

3.6 info() -- 基本信息摘要

info() 方法提供数据集的完整摘要,包括行数、列数、每列的非空值数量、数据类型和内存使用量。

# 查看 DataFrame 基本信息 df.info()
<class 'pandas.core.frame.DataFrame'> Index: 5 entries, A to E Data columns (total 5 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 城市 5 non-null object 1 GDP_2023 5 non-null int64 2 人口_万 5 non-null int64 3 增长率 5 non-null float64 4 是否一线 5 non-null bool dtypes: bool(1), float64(1), int64(2), object(1) memory usage: 245.0+ bytes

实用技巧

df.info(verbose=False) 可以只显示简要信息。对于大型数据集,info() 是快速了解数据全貌的首选方法。

3.7 head() / tail() -- 数据预览

# 查看前3行 print(df.head(3)) # 查看后2行 print(df.tail(2)) # 默认显示前5行 print(df.head())
城市 GDP_2023 人口_万 增长率 是否一线 A 北京 43760 2188 0.052 True B 上海 47218 2475 0.058 True C 广州 30356 1873 0.048 True 城市 GDP_2023 人口_万 增长率 是否一线 D 深圳 34606 1768 0.061 True E 杭州 20059 1237 0.056 False

3.8 describe() -- 统计描述

对数值型列自动计算常用统计量,快速了解数据分布。

# 数值列的统计摘要 print(df.describe())
GDP_2023 人口_万 增长率 count 5.000000 5.000000 5.000000 mean 35399.800000 1908.200000 0.055000 std 9867.744747 458.588956 0.004743 min 20059.000000 1237.000000 0.048000 25% 30356.000000 1768.000000 0.052000 50% 34606.000000 1873.000000 0.056000 75% 43760.000000 2188.000000 0.058000 max 47218.000000 2475.000000 0.061000

describe() 提供以下统计量:count(计数)、mean(均值)、std(标准差)、min(最小值)、25%(第一四分位数)、50%(中位数)、75%(第三四分位数)、max(最大值)。

# 对分类列进行统计 print(df.describe(include=["object", "bool"])) # 对全DataFrame进行统计(包括所有类型) print(df.describe(include="all"))

3.9 memory_usage() -- 内存使用量

了解 DataFrame 的内存占用,对于大型数据集优化非常重要。

# 每列内存使用量(字节) print(df.memory_usage()) print() # 包含索引的内存使用 print(df.memory_usage(index=True)) print() # 深层次内存分析(更准确) print(df.memory_usage(deep=True))
Index 132 城市 40 GDP_2023 40 人口_万 40 增长率 40 是否一线 5 dtype: int64 Index 132 城市 40 GDP_2023 40 人口_万 40 增长率 40 是否一线 5 dtype: int64 Index 132 城市 260 GDP_2023 40 人口_万 40 增长率 40 是否一线 5 dtype: int64

当使用 deep=True 时,会计算 object 类型列中实际字符串的内存占用(上例中"城市"列从 40 字节变为 260 字节,因为字符串实际存储更多内容)。

# 总内存使用 total_memory = df.memory_usage(deep=True).sum() print(f"DataFrame总内存: {total_memory} bytes") print(f"DataFrame总内存: {total_memory / 1024:.2f} KB")
DataFrame总内存: 517 bytes DataFrame总内存: 0.50 KB

属性速查表

属性/方法返回内容常用场景
df.columns列名 Index查看所有列名
df.index行索引查看/设置行索引
df.valuesndarray 数组获取纯数据矩阵
df.dtypes每列数据类型数据清洗前检查类型
df.shape(行, 列) 元组了解数据规模
df.info()完整摘要快速了解数据集全貌
df.head(n)前n行DataFrame预览数据
df.tail(n)后n行DataFrame查看末尾数据
df.describe()统计摘要表数值分布分析
df.memory_usage()每列内存字节数内存优化分析

四、列操作

列的增、删、改、查是 DataFrame 最常用的操作之一。

4.1 T -- 行列转置

T 属性将 DataFrame 的行和列互换,行变成列,列变成行。

# 行列转置 df_T = df.T print(df_T)
A B C D E 城市 北京 上海 广州 深圳 杭州 GDP_2023 43760 47218 30356 34606 20059 人口_万 2188 2475 1873 1768 1237 增长率 0.052 0.058 0.048 0.061 0.056 是否一线 True True True True False

注意

转置后所有列数据类型会变成统一的 object 类型(因为各列原本混合了 int、float、bool、string 等类型)。转置通常用于将样本作为列、特征作为行的场景。

4.2 列的选择

# 选择单列(返回 Series) city = df["城市"] print(type(city)) # print(city) # 选择多列(返回 DataFrame) sub = df[["城市", "GDP_2023"]] print(sub) # 使用 loc 按标签选择 print(df.loc[:, ["城市", "增长率"]]) # 使用 iloc 按位置选择(选择第0列和第3列) print(df.iloc[:, [0, 3]]) # 使用列号范围 print(df.iloc[:, 0:3]) # 第0列到第2列
A 北京 B 上海 C 广州 D 深圳 E 杭州 Name: 城市, dtype: object 城市 GDP_2023 A 北京 43760 B 上海 47218 C 广州 30356 D 深圳 34606 E 杭州 20059 城市 增长率 A 北京 0.052 B 上海 0.058 C 广州 0.048 D 深圳 0.061 E 杭州 0.056 城市 增长率 A 北京 0.052 B 上海 0.058 C 广州 0.048 D 深圳 0.061 E 杭州 0.056 城市 GDP_2023 人口_万 A 北京 43760 2188 B 上海 47218 2475 C 广州 30356 1873 D 深圳 34606 1768 E 杭州 20059 1237

4.3 列的添加

# 添加单列 df["人均GDP"] = df["GDP_2023"] * 10000 / df["人口_万"] print(df[["城市", "GDP_2023", "人口_万", "人均GDP"]].round(2)) # 添加常量列 df["国家"] = "中国" # 使用 insert 在指定位置插入列 df.insert(loc=1, column="省份", value=["北京市", "上海市", "广东省", "广东省", "浙江省"]) # 使用 assign 方法(不修改原df,返回新df) df_new = df.assign(分类=lambda x: "一线" if x["是否一线"] else "新一线")
城市 GDP_2023 人口_万 人均GDP A 北京 43760 2188 200000.00 B 上海 47218 2475 190779.80 C 广州 30356 1873 162070.48 D 深圳 34606 1768 195734.62 E 杭州 20059 1237 162158.45

4.4 列的删除

# 使用 drop 方法(默认返回新DataFrame) df_dropped = df.drop(columns=["人均GDP", "国家"]) print(df_dropped.columns.tolist()) # 原地删除(inplace=True) # df.drop(columns=["人均GDP"], inplace=True) # 使用 del 关键字(原地删除) # del df["人均GDP"] # 使用 pop 方法(删除并返回该列) # removed_col = df.pop("人均GDP") # 删除行(axis=0) df_row_dropped = df.drop(index=["D", "E"]) print(df_row_dropped)

4.5 列的修改

# 基于条件修改列的值 df["是否发达"] = df["GDP_2023"] > 30000 print(df[["城市", "GDP_2023", "是否发达"]]) # 对所有数值列应用函数 df_log = df[["GDP_2023", "人口_万"]].apply(np.log) print(df_log.round(3)) # 替换列中的特定值 df["城市"] = df["城市"].str.replace("市", "") # 注意: 列名本来没有"市"

4.6 列重命名

# 使用 rename 方法 df_renamed = df.rename(columns={ "GDP_2023": "GDP(亿元)", "人口_万": "人口(万人)", "增长率": "GDP增长率" }) print(df_renamed.columns.tolist()) # 原地重命名 # df.rename(columns={"旧名": "新名"}, inplace=True) # 批量添加前缀或后缀 print(df.add_prefix("col_").columns.tolist()) print(df.add_suffix("_suffix").columns.tolist())
['城市', '省份', 'GDP(亿元)', '人口(万人)', 'GDP增长率', '是否一线', '国家', '人均GDP', '是否发达'] ['col_城市', 'col_省份', 'col_GDP_2023', 'col_人口_万', 'col_增长率', 'col_是否一线', 'col_国家', 'col_人均GDP', 'col_是否发达'] ['城市_suffix', '省份_suffix', 'GDP_2023_suffix', '人口_万_suffix', '增长率_suffix', '是否一线_suffix', '国家_suffix', '人均GDP_suffix', '是否发达_suffix']

4.7 列类型转换

# 使用 astype 转换类型 df["GDP_2023"] = df["GDP_2023"].astype(float) print(df.dtypes) # 转换为分类类型(节省内存、提高性能) df["是否一线"] = df["是否一线"].astype("category") print(df["是否一线"].dtype) # category # 使用 pd.to_numeric / to_datetime # s = pd.Series(["1", "2", "3"]) # s_numeric = pd.to_numeric(s, errors="coerce") # coerce将无效值转为NaN # 字符串转日期 # df["日期"] = pd.to_datetime(df["日期"], format="%Y-%m-%d")

常用的类型转换方法对比:

方法适用场景示例
astype()基础类型转换df["col"].astype(float)
pd.to_numeric()字符串转数值pd.to_numeric(s, errors="coerce")
pd.to_datetime()字符串转日期pd.to_datetime(s, format="%Y%m%d")
astype("category")分类数据优化df["col"].astype("category")

4.8 行操作

# 使用 loc 按条件选择行 high_gdp = df.loc[df["GDP_2023"] > 35000] print(high_gdp[["城市", "GDP_2023"]]) # 使用 iloc 按位置选择行 print(df.iloc[0:2, :]) # 前两行 # 添加新行(使用 loc) df.loc["F"] = ["成都", "四川省", 22074, 2126, 0.060, False, "中国", 103849.48, False] # 删除行 df_clean = df.drop(index=["F"]) # 重置索引 df_reset = df.reset_index(drop=True) print(df_reset.head())

五、DataFrame与Series互相转换

5.1 DataFrame 转 Series

# 选取单列得到 Series s = df["城市"] print(type(s)) # print(s.values) # ndarray # 选取单行得到 Series row_series = df.iloc[0] print(type(row_series)) print(row_series) # 使用 squeeze 将单列或单行 DataFrame 转为 Series single_col_df = df[["城市"]] # 这是 DataFrame squeezed = single_col_df.squeeze() print(type(squeezed)) #
['北京' '上海' '广州' '深圳' '杭州'] 城市 北京 省份 北京市 GDP_2023 43760 人口_万 2188 增长率 0.052 是否一线 True 国家 中国 人均GDP 200000.0 是否发达 True Name: A, dtype: object

5.2 Series 转 DataFrame

# 使用 to_frame() 方法 s = pd.Series([100, 200, 300], name="数值") df_from_series = s.to_frame() print(df_from_series) print(type(df_from_series)) # 多个 Series 组合成 DataFrame s1 = pd.Series([1, 2, 3], name="A") s2 = pd.Series([4, 5, 6], name="B") df_combined = pd.concat([s1, s2], axis=1) print(df_combined) # 使用字典包装 Series df_wrapped = pd.DataFrame({"列1": s1, "列2": s2}) print(df_wrapped)
数值 0 100 1 200 2 300 A B 0 1 4 1 2 5 2 3 6

5.3 DataFrame 展开为多个 Series

# 遍历每一列,得到 Series for col_name, col_series in df.items(): print(f"列名: {col_name}, 类型: {type(col_series).__name__}") # 转为字典(列名 -> Series) series_dict = dict(df.items()) print(series_dict.keys())

六、综合实践案例

案例:学生成绩分析

创建一个包含多科成绩的 DataFrame,并进行数据分析。

# ===================== # 步骤1:创建数据 # ===================== import pandas as pd import numpy as np # 生成学生成绩数据 students = ["学生A", "学生B", "学生C", "学生D", "学生E"] subjects = ["语文", "数学", "英语", "科学"] np.random.seed(42) scores = np.random.randint(60, 100, size=(len(students), len(subjects))) df_scores = pd.DataFrame(scores, columns=subjects, index=students) print("=== 原始成绩 ===") print(df_scores)
=== 原始成绩 === 语文 数学 英语 科学 学生A 70 92 74 67 学生B 88 79 96 61 学生C 78 83 86 77 学生D 63 76 89 93 学生E 67 89 82 71
# ===================== # 步骤2:添加计算列 # ===================== df_scores["总分"] = df_scores.sum(axis=1) df_scores["平均分"] = df_scores[subjects].mean(axis=1).round(1) df_scores["最高分"] = df_scores[subjects].max(axis=1) df_scores["最低分"] = df_scores[subjects].min(axis=1) print("=== 添加统计列 ===") print(df_scores) # ===================== # 步骤3:排名 # ===================== df_scores["排名"] = df_scores["总分"].rank(ascending=False).astype(int) df_sorted = df_scores.sort_values("排名") print("=== 按排名排序 ===") print(df_sorted)
=== 添加统计列 === 语文 数学 英语 科学 总分 平均分 最高分 最低分 学生A 70 92 74 67 303 75.8 92 67 学生B 88 79 96 61 324 81.0 96 61 学生C 78 83 86 77 324 81.0 86 77 学生D 63 76 89 93 321 80.2 93 63 学生E 67 89 82 71 309 77.2 89 67 === 按排名排序 === 语文 数学 英语 科学 总分 平均分 最高分 最低分 排名 学生B 88 79 96 61 324 81.0 96 61 1 学生C 78 83 86 77 324 81.0 86 77 1 学生D 63 76 89 93 321 80.2 93 63 3 学生E 67 89 82 71 309 77.2 89 67 4 学生A 70 92 74 67 303 75.8 92 67 5
# ===================== # 步骤4:列操作 # ===================== # 重命名列名为英文 df_eng = df_scores.rename(columns={ "语文": "Chinese", "数学": "Math", "英语": "English", "科学": "Science" }) print("=== 列重命名 ===") print(df_eng.columns.tolist()) # 查看数据概况 print("\n=== 数据类型 ===") print(df_scores.dtypes) print("\n=== 统计描述 ===") print(df_scores.describe().round(1)) # 转置查看 print("\n=== 行列转置 ===") print(df_scores.T.head(8))
=== 列重命名 === ['Chinese', 'Math', 'English', 'Science', '总分', '平均分', '最高分', '最低分', '排名'] === 数据类型 === 语文 int32 数学 int32 英语 int32 科学 int32 总分 int32 平均分 float64 最高分 int32 最低分 int32 排名 int32 dtype: object === 统计描述 === 语文 数学 英语 科学 总分 平均分 最高分 最低分 排名 count 5.0 5.0 5.0 5.0 5.0 5.0 5.0 5.0 5.0 mean 73.2 83.8 85.4 73.8 316.2 79.1 91.2 67.8 2.8 std 9.9 7.0 8.2 12.4 10.1 2.5 3.0 6.8 1.8 min 63.0 76.0 74.0 61.0 303.0 75.8 86.0 61.0 1.0 25% 67.0 79.0 82.0 67.0 309.0 77.2 89.0 63.0 1.0 50% 70.0 83.0 86.0 71.0 321.0 80.2 92.0 67.0 3.0 75% 78.0 89.0 89.0 77.0 324.0 81.0 93.0 67.0 4.0 max 88.0 92.0 96.0 93.0 324.0 81.0 96.0 77.0 5.0
# ===================== # 步骤5:内存分析 # ===================== print("=== 内存使用分析 ===") print(df_scores.memory_usage(deep=True)) total_bytes = df_scores.memory_usage(deep=True).sum() print(f"总内存: {total_bytes} bytes ({total_bytes/1024:.2f} KB)")
=== 内存使用分析 === Index 145 语文 40 数学 40 英语 40 科学 40 总分 40 平均分 40 最高分 40 最低分 40 排名 40 dtype: int64 总内存: 505 bytes (0.49 KB)

七、常见问题与最佳实践

问题1:SettingWithCopyWarning

当对 DataFrame 的切片视图进行赋值操作时,Pandas 会发出警告。应使用 .loc 明确操作或使用 .copy() 创建副本。

# 错误的做法(会警告) # subset = df[df["GDP_2023"] > 30000] # subset["新列"] = 1 # SettingWithCopyWarning! # 正确的做法 subset = df.loc[df["GDP_2023"] > 30000].copy() subset["新列"] = 1 # 安全

问题2:链式索引与性能

避免链式索引(如 df["col1"]["row1"]),应使用 df.loc["row1", "col1"],既清晰又高效。

最佳实践清单

  • 选择列:单列用 df["col"],多列用 df[["col1", "col2"]]
  • 选择行:标签用 .loc[],位置用 .iloc[],条件用布尔索引
  • 修改数据:始终使用 .loc.iloc,避免链式赋值
  • 添加列:直接赋值 df["新列"] = ... 或使用 .assign()
  • 类型转换:使用 .astype()pd.to_numeric()/pd.to_datetime()
  • 内存优化:对低基数分类列使用 category 类型
  • 数据预览:使用 .head()/.tail()/.info()/.describe() 快速了解数据

八、核心要点总结

  • DataFrame核心地位:Pandas中最重要的二维表格数据结构,兼具行列标签
  • 创建方式多样:支持从dict、list、ndarray、Series、CSV等多种来源创建,选择灵活
  • 属性体系完整:columns(列名)、index(行索引)、values(数据值)、dtypes(类型)、shape(形状)构成基础属性体系
  • 快速数据预览:info() 查看完整摘要、describe() 给出统计描述、head()/tail() 快速预览
  • 列操作灵活:增删改查、重命名、类型转换、排序,覆盖日常数据处理所有需求
  • 行列转置T:快速交换行列位置,适用于数据格式转换场景
  • 内存可量化:memory_usage() 精确查看每列和数据整体内存占用
  • 双向转换:DataFrame与Series可互相转换,单列即Series,多个Series可组合为DataFrame
  • 遵循最佳实践:使用 .loc/.iloc 选择数据、用 .copy() 避免警告、用 category 类型优化内存

九、进一步学习

掌握 DataFrame 的创建和属性后,建议继续学习以下进阶主题:

  • 数据清洗:缺失值处理(isna/dropna/fillna)、重复值处理(duplicated/drop_duplicates)
  • 数据聚合:groupby 分组聚合、pivot_table 透视表、crosstab 交叉表
  • 数据合并:concat 拼接、merge 合并(类SQL连接)、join 索引连接
  • 时间序列:日期范围、重采样(resample)、滑动窗口(rolling)
  • 数据可视化:结合 Matplotlib/Seaborn 进行数据探索与展示
  • 性能优化:向量化操作替代循环、使用 eval()/query() 加速、大数据分块读取

推荐资源

  • Pandas 官方文档:https://pandas.pydata.org/docs/
  • Pandas Cheat Sheet:官方提供的速查表覆盖大部分常用操作
  • 《利用Python进行数据分析》(Wes McKinney 著)—— Pandas 作者亲笔