Python — Pandas

Pandas

官方文档 https://pandas.pydata.org/docs/index.html

数据集 #

列几个数据集用于测试:

  1. https://learn.microsoft.com/en-us/power-bi/create-reports/sample-financial-download (Financial.xlsx)
  2. https://www.gairuo.com/file/data/dataset/team.xlsx (team.xlsx)

查看数据 #

df.head() # 头部 5 条
df.tail() # 尾部 5 条
df.sample() # 随机查看 5 条

df.shape # (100, 6) 查看行数和列数
df.info() # 查看索引、数据类型和内存信息
df.describe() # 查看数值型列的汇总统计
df.dtypes # 查看各字段类型
df.axes # 显示数据行和列名
df.columns # 列名

选取数据 #

选择列 #

df["Q1"] # 指定列
df.Q1 # 同上一行

df[['team', 'Q1']] # 只看这两列
df.loc[:, ['team', 'Q1']] # 同上一行

选择行 #

df[df.index == 'Liver'] # 根据索引名称

# 根据自然索引
df[0:3] # 取前三个
df[0:10:2] # 前 10 个每隔两个取一个
df.iloc[:10, :] # 前 10 个

指定行和列 #

df.loc['Ben', 'Q1':'Q4']
df.loc['A': 'D', 'Q1': 'Q4']

条件选择 #

df[df.Q1 > 90] # Q1 大于 90 的
df[df.team == 'C'] # team 列为 'C' 的
df[df.index == 'Oscar'] # 指定 index 名称

运算数据 #

排序 #

df.sort_values(by="Q1", ascending=False) # 按 Q1 降序排列, default is True

分组聚合 #

df.groupby('team').sum() # 求和
df.groupby('team').mean() # 求平均
df.groupby('team').agg({'Q1': sum, 'Q2': count, 'Q3': 'mean', 'Q4': max}) # agg 很强大

数据反转 #

df.T 应该能玩出花。

数据降维 #

df.groupby('team').sum().stack()
df.groupby('team').sum().unstack()

举个例子:

>>> df_single_level_cols
     weight height
cat       0      1
dog       2      3
>>> df_single_level_cols.stack()
cat  weight    0
     height    1
dog  weight    2
     height    3
dtype: int64

数据统计 #

df.mean()
df.corr() # 返回列与列之间的相关系数
df.max()
df.min()
df.std() # 标准差
df.var() # 方差
df.mode() # 众数
df.median() # 中位数

绘图 #

df.plot()

导出 #

支持 CSV 、 Excel 、 HTML 等常见格式。

MultiIndex #

参考 #

深入浅出Pandas

Pandas 常用操作:数据筛选、查询与更新 #

Pandas 是 Python 中最强大的数据处理库之一,特别擅长数据筛选、查询和更新操作。以下是一些常用场景和技巧。

1. 数据筛选与查询 #

1.1 基本条件筛选 #

import pandas as pd
import numpy as np

# 创建示例 DataFrame
df = pd.DataFrame({
    'name': ['Alice', 'Bob', 'Charlie', 'David', 'Eva'],
    'age': [25, 30, 35, 40, 45],
    'city': ['New York', 'London', 'Paris', 'Tokyo', 'Berlin'],
    'salary': [50000, 60000, 70000, 80000, 90000],
    'department': ['IT', 'HR', 'IT', 'Finance', 'HR']
})

# 1. 简单条件筛选
young_employees = df[df['age'] < 35]
it_employees = df[df['department'] == 'IT']

# 2. 多条件筛选
it_young = df[(df['department'] == 'IT') & (df['age'] < 40)]
hr_or_finance = df[(df['department'] == 'HR') | (df['department'] == 'Finance')]

# 3. 使用 isin 进行多值筛选
selected_cities = df[df['city'].isin(['New York', 'Paris', 'Berlin'])]

# 4. 使用 query 方法
high_salary = df.query('salary > 65000 and age > 30')

1.2 字符串筛选 #

# 1. 字符串包含
names_with_a = df[df['name'].str.contains('a')]

# 2. 字符串开头/结尾
names_starting_with_a = df[df['name'].str.startswith('A')]
names_ending_with_e = df[df['name'].str.endswith('e')]

# 3. 正则表达式匹配
names_with_vowel_ending = df[df['name'].str.contains('[aeiou]$', regex=True)]

1.3 基于索引的筛选 #

# 1. 按位置选择
first_three = df.iloc[:3]  # 前3行
specific_rows = df.iloc[[0, 2, 4]]  # 第0,2,4行

# 2. 按标签选择
df_indexed = df.set_index('name')
alice_info = df_indexed.loc['Alice']
multiple_people = df_indexed.loc[['Alice', 'Charlie', 'Eva']]

2. 数据更新操作 #

2.1 修改列值 #

# 1. 直接修改列
df['salary'] = df['salary'] * 1.1  # 给所有人加薪10%

# 2. 条件更新
df.loc[df['department'] == 'IT', 'salary'] = df['salary'] * 1.15  # IT部门加薪15%

# 3. 使用 apply 函数
df['age_group'] = df['age'].apply(
    lambda x: 'Young' if x < 30 else 'Middle-aged' if x < 45 else 'Senior'
)

# 4. 使用 np.where
df['bonus'] = np.where(df['salary'] > 70000, 5000, 3000)

2.2 添加新列 #

# 1. 基于计算
df['annual_bonus'] = df['salary'] * 0.1

# 2. 基于多列计算
df['total_compensation'] = df['salary'] + df['annual_bonus']

# 3. 使用 assign 方法(返回新DataFrame)
df_new = df.assign(
    tax = df['salary'] * 0.2,
    net_salary = df['salary'] * 0.8
)

2.3 处理缺失值 #

# 创建有缺失值的示例数据
df_with_nan = pd.DataFrame({
    'A': [1, 2, np.nan, 4, 5],
    'B': [np.nan, 2, 3, np.nan, 5],
    'C': [1, 2, 3, 4, 5]
})

# 1. 检测缺失值
missing_values = df_with_nan.isnull()
missing_count = df_with_nan.isnull().sum()

# 2. 填充缺失值
filled_df = df_with_nan.fillna(0)  # 用0填充
filled_mean = df_with_nan.fillna(df_with_nan.mean())  # 用列均值填充

# 3. 删除缺失值
dropped_any = df_with_nan.dropna()  # 删除任何包含NaN的行
dropped_all = df_with_nan.dropna(how='all')  # 只删除全部为NaN的行

3. 高级查询技巧 #

3.1 使用 query 方法 #

# 1. 基本查询
result = df.query('age > 30 and salary > 60000')

# 2. 使用变量
min_age = 30
max_salary = 80000
result = df.query('age > @min_age and salary < @max_salary')

# 3. 复杂条件
result = df.query('(department == "IT" and age < 40) or (department == "HR" and salary > 65000)')

3.2 使用 eval 进行高效计算 #

# 对于大型DataFrame,eval可以更高效
df = pd.DataFrame(np.random.randn(10000, 4), columns=['A', 'B', 'C', 'D'])

# 传统方式
result1 = df[(df.A < 0.5) & (df.B > 0.5)]

# 使用eval(更高效)
result2 = df.eval('A < 0.5 and B > 0.5')

3.3 多层条件筛选 #

# 创建多层索引示例
arrays = [['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux'],
          ['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two']]
tuples = list(zip(*arrays))
index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second'])
df_multi = pd.DataFrame(np.random.randn(8, 4), index=index, columns=['A', 'B', 'C', 'D'])

# 多层索引查询
result = df_multi.xs('bar', level='first')  # 获取first级别为'bar'的所有行
result = df_multi.xs(('bar', 'one'), level=['first', 'second'])  # 获取特定组合

4. 数据分组与聚合 #

4.1 基本分组操作 #

# 1. 按部门分组
grouped = df.groupby('department')

# 2. 获取分组统计
department_stats = grouped.agg({
    'salary': ['mean', 'min', 'max', 'std'],
    'age': 'mean'
})

# 3. 对每个分组应用函数
def top_earner(group):
    return group.nlargest(1, 'salary')

top_earners_by_dept = grouped.apply(top_earner)

4.2 分组后更新数据 #

# 计算每个部门的平均工资
dept_avg_salary = df.groupby('department')['salary'].transform('mean')

# 添加新列显示与部门平均工资的差异
df['salary_diff_from_dept'] = df['salary'] - dept_avg_salary

# 为每个部门内的员工按工资排序
df['dept_salary_rank'] = df.groupby('department')['salary'].rank(ascending=False)

5. 处理日期数据 #

# 创建日期示例数据
date_rng = pd.date_range(start='2023-01-01', end='2023-01-10', freq='D')
df_dates = pd.DataFrame(date_rng, columns=['date'])
df_dates['value'] = np.random.randint(1, 100, size=(len(date_rng)))

# 1. 设置日期索引
df_dates.set_index('date', inplace=True)

# 2. 按时间范围筛选
jan_first_week = df_dates['2023-01-01':'2023-01-07']

# 3. 重采样(例如按周计算平均值)
weekly_avg = df_dates.resample('W').mean()

# 4. 提取日期部分
df_dates['year'] = df_dates.index.year
df_dates['month'] = df_dates.index.month
df_dates['day'] = df_dates.index.day

6. 性能优化技巧 #

6.1 使用合适的数据类型 #

# 查看当前数据类型
print(df.dtypes)

# 优化数据类型以减少内存使用
df['department'] = df['department'].astype('category')
df['city'] = df['city'].astype('category')

# 对于整数列,使用最小位数的整数类型
df['age'] = df['age'].astype('int8')

6.2 使用向量化操作 #

# 避免使用循环,使用向量化操作
# 慢的方式
def calculate_bonus(row):
    if row['department'] == 'IT':
        return row['salary'] * 0.15
    else:
        return row['salary'] * 0.10

# 快的方式(向量化)
df['bonus'] = np.where(df['department'] == 'IT', df['salary'] * 0.15, df['salary'] * 0.10)

7. 实用小技巧 #

7.1 随机抽样 #

# 随机抽取3行
sample = df.sample(n=3)

# 按比例抽样(20%)
sample_frac = df.sample(frac=0.2)

# 分层抽样(按部门)
stratified = df.groupby('department').apply(lambda x: x.sample(frac=0.3))

7.2 处理重复值 #

# 检测重复行
duplicates = df.duplicated()

# 删除完全重复的行
df_no_duplicates = df.drop_duplicates()

# 基于特定列删除重复行
df_no_duplicates_name = df.drop_duplicates(subset=['name'])

# 保留第一次出现或最后一次出现
df_keep_first = df.drop_duplicates(subset=['name'], keep='first')
df_keep_last = df.drop_duplicates(subset=['name'], keep='last')

这些操作涵盖了 Pandas 在数据筛选、查询和更新方面的常见用法。掌握这些技巧将大大提高数据处理的效率和能力。

本文共 1778 字,创建于 Nov 12, 2022

相关标签: Python