Pandas Series API 手册
Pandas Series API 完整手册
1. Series 创建
1.1 基本创建方法
import pandas as pd
import numpy as np
# 从列表/数组创建
s1 = pd.Series([1, 3, 5, np.nan, 6, 8])
s2 = pd.Series(np.arange(10))
# 从字典创建
s3 = pd.Series({'a': 1, 'b': 2, 'c': 3})
# 指定索引
s4 = pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])
s5 = pd.Series([10, 20, 30], index=pd.date_range('2023-01-01', periods=3))
# 从标量创建
s6 = pd.Series(5, index=['a', 'b', 'c']) # 全为5
s7 = pd.Series(5.0, index=range(5))
# 空Series
s_empty = pd.Series(dtype='float64')
print("Series示例:")
print(s1)
print("\n索引:", s1.index)
print("值:", s1.values)
print("类型:", s1.dtype)
1.2 高级创建
# 指定数据类型
s_int = pd.Series([1, 2, 3], dtype='int32')
s_float = pd.Series([1.0, 2.0, 3.0], dtype='float32')
s_category = pd.Series(['A', 'B', 'A'], dtype='category')
# 带名称的Series
s_named = pd.Series([1, 2, 3], name='values', index=['x', 'y', 'z'])
# 从其他Series复制
s_copy = s1.copy(deep=True)
# 使用pd.array创建(Pandas 0.24+)
s_arrow = pd.Series(pd.array([1, 2, None], dtype='Int64')) # 可空整数
2. 属性和方法
2.1 基本属性
s = pd.Series([10, 20, 30, 40], index=['a', 'b', 'c', 'd'])
# 基本信息
print("长度:", len(s))
print("形状:", s.shape)
print("索引:", s.index)
print("值:", s.values)
print("数据类型:", s.dtype)
print("名称:", s.name)
print("是否为空:", s.empty)
print("轴:", s.axes)
# 内存使用
print("内存使用:", s.memory_usage(index=True, deep=True))
# 数据类型信息
print("可空类型:", s.dtype.name)
print("是否为可空:", s.dtype.is_nullable)
2.2 索引属性
# 索引操作
print("索引类型:", type(s.index))
print("索引值:", s.index.tolist())
print("是否唯一:", s.index.is_unique)
print("是否单调递增:", s.index.is_monotonic_increasing)
# 设置名称
s.index.name = 'labels'
print("索引名称:", s.index.name)
3. 索引和选择
3.1 位置索引(iloc)
s = pd.Series([10, 20, 30, 40, 50], index=['a', 'b', 'c', 'd', 'e'])
# 单个元素
print("位置索引0:", s.iloc[0]) # 10
print("位置索引-1:", s.iloc[-1]) # 50
# 切片
print("位置切片0:2:", s.iloc[0:2]) # a, b
print("位置切片1:", s.iloc[1:]) # b, c, d, e
# 列表索引
print("位置列表[0,2,4]:", s.iloc[[0, 2, 4]]) # a, c, e
# 布尔索引
mask = s.iloc > 25
print("布尔选择:", s.iloc[mask])
3.2 标签索引(loc)
# 单个标签
print("标签'a':", s.loc['a']) # 10
# 标签切片
print("标签切片a:c:", s.loc['a':'c']) # a, b, c
# 标签列表
print("标签列表['a','c','e']:", s.loc[['a', 'c', 'e']])
# 条件索引
print("条件选择 (值>25):", s.loc[s > 25])
# 多条件
print("多条件:", s.loc[(s > 20) & (s.index != 'b')])
3.3 混合索引(at/iat)
# 快速单元素访问(更快但只支持单个元素)
print("at标签'a':", s.at['a']) # 10
print("iat位置0:", s.iat[0]) # 10
# 警告:不支持切片
# s.at['a':'c'] # TypeError
3.4 高级索引
# 索引不存在时的行为
try:
s.loc['missing']
except KeyError as e:
print("KeyError:", e)
# 使用get方法(安全)
print("get('missing', default=-1):", s.get('missing', default=-1))
# 部分匹配(模糊索引)
print("部分匹配:", s.loc[s.index.str.startswith('a')])
# 多级索引(如果索引是MultiIndex)
index = pd.MultiIndex.from_product([['A', 'B'], [1, 2]])
s_multi = pd.Series(np.arange(4), index=index)
print("多级索引:", s_multi.loc['A']) # 选择第一级
4. 数据操作
4.1 赋值和修改
s = pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])
# 直接赋值
s['a'] = 10
s.iloc[1] = 20
# 批量赋值
s.loc[['b', 'c']] = [200, 300]
s.iloc[0:2] = [100, 200]
# 条件赋值
s.loc[s > 200] = 0
# 使用update方法
s2 = pd.Series([999, 888], index=['a', 'b'])
s.update(s2)
print("更新后:", s)
4.2 插入和删除
# 插入
s = pd.Series([1, 2, 3], index=['a', 'b', 'c'])
s['d'] = 4
s2 = s.append(pd.Series([5], index=['e'])) # 旧方法,已弃用
s_new = pd.concat([s, pd.Series([5], index=['e'])]) # 新方法
# 删除
s_dropped = s.drop('c')
s_dropped2 = s.drop(['a', 'b'])
# 使用del
del s['a']
print("删除后:", s)
4.3 排序
s = pd.Series([3, 1, 4, 1, 5], index=['e', 'a', 'b', 'c', 'd'])
# 按值排序
s_sorted = s.sort_values()
print("按值排序:", s_sorted)
# 按索引排序
s_idx_sorted = s.sort_index()
print("按索引排序:", s_idx_sorted)
# 带参数排序
s_sorted_asc = s.sort_values(ascending=False, na_position='first')
s_stable = s.sort_values(ascending=True, kind='stable') # 稳定排序
# 忽略索引排序
s_values_only = s.sort_values().reset_index(drop=True)
5. 缺失值处理
5.1 检测缺失值
s = pd.Series([1, np.nan, 3, None, 5])
# 检测
print("是否有NaN:", s.hasnans)
print("NaN位置:", s.isna())
print("非NaN位置:", s.notna())
print("NaN数量:", s.isna().sum())
# 特定值检查
print("是否全为NaN:", s.isna().all())
print("是否部分NaN:", s.isna().any())
5.2 填充缺失值
# 常用填充方法
s_filled = s.fillna(0) # 用0填充
s_forward = s.fillna(method='ffill') # 前向填充
s_backward = s.fillna(method='bfill') # 后向填充
# 指定值填充
s_mean = s.fillna(s.mean())
s_median = s.fillna(s.median())
# 插值填充
s_interp = s.interpolate(method='linear')
s_time = pd.Series([1, np.nan, np.nan, 4],
index=pd.date_range('2023-01-01', periods=4))
s_time_interp = s_time.interpolate(method='time')
# 组合填充
s_combined = s.fillna(method='ffill').fillna(0)
print("填充结果:", s_filled)
5.3 删除缺失值
# 删除含NaN的元素
s_clean = s.dropna()
# 按阈值删除(至少保留n个非NaN值)
s_threshold = s.dropna(thresh=2)
print("删除NaN后:", s_clean)
6. 统计方法
6.1 描述性统计
s = pd.Series(np.random.randn(1000))
print("描述性统计:")
print(s.describe())
# 单独统计量
print("均值:", s.mean())
print("中位数:", s.median())
print("标准差:", s.std())
print("方差:", s.var())
print("最小值:", s.min())
print("最大值:", s.max())
print("四分位数:", s.quantile([0.25, 0.5, 0.75]))
6.2 聚合函数
# 基本聚合
print("总和:", s.sum())
print("计数(非NaN):", s.count())
print("累积和:", s.cumsum())
print("累积最大:", s.cummax())
print("累积最小:", s.cummin())
# 移动统计
print("滚动均值:", s.rolling(5).mean().head())
print("扩展统计:", s.expanding().mean().head())
# 分位数
print("95%分位:", s.quantile(0.95))
6.3 相关性
s1 = pd.Series(np.random.randn(100))
s2 = pd.Series(np.random.randn(100))
# 皮尔逊相关系数
corr = s1.corr(s2)
print("相关系数:", corr)
# 协方差
cov = s1.cov(s2)
print("协方差:", cov)
# 自动相关
autocorr = s1.autocorr(lag=1)
print("自相关:", autocorr)
7. 字符串方法(str访问器)
7.1 基本字符串操作
s_str = pd.Series(['Apple', 'Banana', 'Cherry', None, 'Date'])
# 长度
print("字符串长度:", s_str.str.len())
# 大小写
print("大写:", s_str.str.upper())
print("小写:", s_str.str.lower())
print("标题:", s_str.str.title())
# 查找和替换
print("包含'A':", s_str.str.contains('A'))
print("替换:", s_str.str.replace('a', 'A'))
# 分割和提取
print("首字母:", s_str.str[0])
print("分割:", s_str.str.split(''))
7.2 正则表达式
email_s = pd.Series(['user@example.com', 'test@domain.org', None])
# 正则匹配
print("是邮箱:", email_s.str.match(r'^[\w\.-]+@[\w\.-]+\.\w+$'))
print("提取域名:", email_s.str.extract(r'@([\w\.-]+)'))
# 查找所有匹配
print("所有匹配:", email_s.str.findall(r'\w+'))
# 替换正则
print("替换数字:", s_str.str.replace(r'\d+', '', regex=True))
7.3 高级字符串方法
# 去除空格
print("去除空格:", s_str.str.strip())
# 填充
print("左填充:", s_str.str.pad(10, side='left', fillchar=' '))
print("居中:", s_str.str.center(10, fillchar='-'))
# 翻译
trans_map = str.maketrans('ae', 'AE')
print("翻译:", s_str.str.translate(trans_map))
# 格式化
print("格式化:", s_str.str.zfill(10)) # 数字字符串补0
8. 数值方法(数值Series)
8.1 数学运算
s_num = pd.Series([1, 2, 3, 4])
# 基本运算
print("加法:", s_num + 10)
print("乘法:", s_num * 2)
print("幂运算:", s_num ** 2)
# 应用函数
print("平方根:", np.sqrt(s_num))
print("对数:", np.log(s_num))
print("指数:", np.exp(s_num - 1))
# 自定义函数
print("自定义:", s_num.apply(lambda x: x**2 + 1))
8.2 统计函数
# 排名
print("排名:", s_num.rank(method='average'))
# 差分
print("一阶差分:", s_num.diff())
print("二阶差分:", s_num.diff(2))
# 百分比变化
print("百分比变化:", s_num.pct_change())
# 移动窗口
print("移动最大:", s_num.rolling(2).max())
8.3 数值转换
# 舍入
print("四舍五入:", s_num.round(1))
print("向下取整:", np.floor(s_num))
print("向上取整:", np.ceil(s_num))
# 裁剪
print("裁剪到[1, 3]:", s_num.clip(lower=1, upper=3))
# 标准化
print("Z-score:", (s_num - s_num.mean()) / s_num.std())
9. 时间序列功能
9.1 创建时间序列
# 日期范围索引
dates = pd.date_range('2023-01-01', periods=5, freq='D')
ts = pd.Series(np.random.randn(5), index=dates)
# 从字符串解析
ts_str = pd.to_datetime(['2023-01-01', '2023-01-02', '2023-01-03'])
ts2 = pd.Series([1, 2, 3], index=ts_str)
print("时间序列:", ts)
9.2 时间属性
# 日期时间属性
print("年份:", ts.index.year)
print("月份:", ts.index.month)
print("星期几:", ts.index.day_name())
print("是否周末:", ts.index.dayofweek.isin([5, 6]))
# 时间段
print("季度:", ts.index.quarter)
print("是否闰年:", ts.index.is_leap_year)
9.3 时间操作
# 移位
print("向前移位:", ts.shift(1))
print("向后移位:", ts.shift(-1))
# 重采样
monthly = ts.resample('M').mean()
print("月度重采样:", monthly)
# 滚动窗口
rolling = ts.rolling('3D').mean()
print("3天滚动均值:", rolling)
10. 分类数据
10.1 创建分类Series
# 分类Series
cat_s = pd.Series(['A', 'B', 'A', 'C', 'B'],
dtype=pd.CategoricalDtype(categories=['A', 'B', 'C'], ordered=True))
print("分类Series:", cat_s)
print("分类:", cat_s.dtype.categories)
print("有序:", cat_s.dtype.ordered)
print("编码:", cat_s.cat.codes)
10.2 分类操作
# 添加/删除分类
cat_s = cat_s.cat.add_categories('D')
print("添加分类D:", cat_s.cat.categories)
# 移除未使用分类
cat_s = cat_s.cat.remove_unused_categories()
print("移除未用分类:", cat_s.cat.categories)
# 重命名分类
cat_s = cat_s.cat.rename_categories({'A': 'Excellent', 'B': 'Good', 'C': 'Poor'})
# 排序(基于分类顺序)
print("分类排序:", cat_s.sort_values())
11. 高级功能
11.1 映射和转换
# map方法
def custom_map(x):
return x * 2 if x > 0 else 0
s_mapped = s.map(custom_map)
print("映射结果:", s_mapped)
# apply方法(更灵活)
s_applied = s.apply(lambda x: x**2)
print("apply结果:", s_applied)
# replace方法
s_replaced = s.replace({1: 100, 2: 200})
print("替换结果:", s_replaced)
11.2 组合操作
s1 = pd.Series([1, 2, 3], index=['a', 'b', 'c'])
s2 = pd.Series([4, 5, 6], index=['b', 'c', 'd'])
# 连接
s_concat = pd.concat([s1, s2])
print("连接:", s_concat)
# 合并(类似SQL join)
s_merge = s1.combine_first(s2)
print("合并:", s_merge)
# 按索引对齐运算
s_aligned = s1 + s2
print("对齐运算:", s_aligned)
11.3 窗口函数
# 滚动窗口
rolling_mean = s.rolling(window=3).mean()
rolling_sum = s.rolling(window=3).sum()
rolling_std = s.rolling(window=3).std()
# 自定义窗口函数
def custom_window(x):
return x.max() - x.min()
rolling_range = s.rolling(3).apply(custom_window)
# 指数加权
ewm_mean = s.ewm(span=3).mean()
# 扩展窗口
expanding_mean = s.expanding().mean()
12. 输入输出
12.1 Series IO
s = pd.Series(np.random.randn(100))
# CSV
s.to_csv('series.csv')
s_csv = pd.read_csv('series.csv', index_col=0, squeeze=True)
# JSON
s.to_json('series.json')
s_json = pd.read_json('series.json', typ='series')
# Pickle
s.to_pickle('series.pkl')
s_pkl = pd.read_pickle('series.pkl')
# 剪贴板
s.to_clipboard()
s_clip = pd.read_clipboard(index_col=0, squeeze=True)
12.2 数据库操作
# 写入数据库
s.to_sql('series_table', engine, if_exists='replace')
# 从数据库读取
s_db = pd.read_sql('SELECT * FROM series_table', engine, index_col='index').squeeze()
13. 最佳实践和性能优化
13.1 性能优化
# 1. 使用向量化操作而非apply
s_vec = s * 2 # 向量化,快速
# s.apply(lambda x: x * 2) # 慢
# 2. 选择合适的数据类型
s_int8 = s.astype('int8') if s.dtype.kind == 'i' else s
s_category = s.astype('category') if s.dtype == 'O' and s.nunique() < len(s) * 0.5 else s
# 3. 使用get而不是直接索引
value = s.get('key', default=np.nan) # 安全
# 4. 批量操作
mask = s > s.median()
s.loc[mask] = 0 # 批量赋值
13.2 内存优化
def optimize_series_memory(s):
"""优化Series内存使用"""
optimized = s.copy()
# 数值类型优化
if optimized.dtype.kind in 'if':
optimized = pd.to_numeric(optimized, downcast='integer' if 'i' in optimized.dtype.kind else 'float')
# 字符串→分类
if optimized.dtype == 'O':
nunique = optimized.nunique()
if nunique / len(optimized) < 0.5:
optimized = optimized.astype('category')
# 布尔优化
if set(optimized.dropna().unique()) <= {True, False}:
optimized = optimized.astype(bool)
return optimized
s_opt = optimize_series_memory(s)
print(f"优化前内存: {s.memory_usage(deep=True)}")
print(f"优化后内存: {s_opt.memory_usage(deep=True)}")
13.3 错误处理
def safe_series_operation(s, operation):
"""安全的Series操作"""
try:
if operation == 'mean':
return s.mean()
elif operation == 'sum':
return s.sum()
# 添加更多操作
except Exception as e:
print(f"操作失败: {e}")
return np.nan
# 使用
result = safe_series_operation(s, 'mean')
Pandas Series 是处理一维数据的核心数据结构,提供了丰富的索引、统计、时间序列和字符串处理功能。通过掌握这些API,可以高效处理各种数据分析任务。关键是选择合适的索引方法、优化数据类型,并优先使用向量化操作以获得最佳性能。