跳到主要内容

Pandas

问题

Pandas 的 DataFrame 核心操作有哪些?如何处理大数据量?

答案

核心数据结构

import pandas as pd

# Series:一维带标签数组
s = pd.Series([1, 2, 3], index=["a", "b", "c"])

# DataFrame:二维带标签表格
df = pd.DataFrame({
"name": ["Alice", "Bob", "Charlie"],
"age": [25, 30, 35],
"salary": [50000, 60000, 70000],
})

数据读写

# CSV
df = pd.read_csv("data.csv", dtype={"id": str}, parse_dates=["created_at"])
df.to_csv("output.csv", index=False)

# Parquet(推荐大文件)
df = pd.read_parquet("data.parquet")
df.to_parquet("output.parquet")

# SQL
df = pd.read_sql("SELECT * FROM users", engine)

分组聚合

# groupby + 聚合
result = df.groupby("department").agg(
avg_salary=("salary", "mean"),
count=("name", "count"),
max_salary=("salary", "max"),
).reset_index()

# 自定义聚合
df.groupby("department")["salary"].apply(lambda x: x.quantile(0.9))

# 透视表
pivot = df.pivot_table(
values="salary",
index="department",
columns="level",
aggfunc="mean",
)

数据清洗

# 缺失值处理
df.dropna(subset=["email"]) # 删除空行
df["age"].fillna(df["age"].median()) # 中位数填充
df["name"].isna().sum() # 统计缺失数

# 类型转换
df["date"] = pd.to_datetime(df["date"])
df["price"] = df["price"].astype(float)

# 去重
df.drop_duplicates(subset=["email"], keep="first")

# 字符串操作
df["name"] = df["name"].str.strip().str.lower()

性能优化

# 1. 减少内存:指定 dtype
df = pd.read_csv("data.csv", dtype={"id": "int32", "flag": "category"})

# 2. 按块读取大文件
for chunk in pd.read_csv("big.csv", chunksize=10000):
process(chunk)

# 3. 使用 Parquet 代替 CSV(压缩 + 列式存储)
df.to_parquet("data.parquet", compression="snappy")

# 4. 向量化操作代替 apply
df["new"] = df["a"] + df["b"] # ✅ 比 apply 快 100x

常见面试问题

Q1: Pandas 和 Polars 的区别?

答案

特性PandasPolars
语言C/CythonRust
并行单线程多线程
惰性求值LazyFrame
内存模型行索引Apache Arrow 列式
速度基准快 5-30x
生态极丰富快速增长

Q2: apply 为什么慢?

答案

apply 会对每一行调用 Python 函数,经过 Python 解释器。向量化操作直接调用 C 扩展。优先用内置方法(str., dt., 算术运算)代替 apply

Q3: mergejoin 的区别?

答案

# merge:基于列合并(类似 SQL JOIN)
result = pd.merge(df1, df2, on="user_id", how="left")

# join:基于索引合并
result = df1.join(df2, how="inner")

# concat:纵向/横向拼接
result = pd.concat([df1, df2], axis=0) # 纵向拼接

Q4: 如何处理时间序列?

答案

df["date"] = pd.to_datetime(df["date"])
df.set_index("date", inplace=True)

# 重采样
monthly = df.resample("M").mean() # 月平均
weekly = df.resample("W").sum() # 周求和

# 滚动窗口
df["ma7"] = df["price"].rolling(7).mean() # 7 日均线

相关链接