DataFrame的数据透视,表的打横操作

现在有这样一个数据:

需要将area列进行打横,数据列是sales,转换成这样:

1. 使用DataFrame自带的pivot_table()方法

优点:设计上更加直观和用户友好,提供了直接的参数来指定行、列、值以及聚合函数。对于大多数数据透视的需求,pivot_table 提供了一种更为简洁的方法。

缺点:虽然强大,但在某些高级用例中不如 groupby + unstack 灵活。

import pandas as pd
# 创建示例数据
data = {
    'area': ['North', 'South', 'East', 'West'] * 3,
    'sales': [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120],
    'date': pd.date_range(start='2024-01-01', periods=12)
}
df = pd.DataFrame(data)
​
# pivot_table参数解析
"""
data: DataFrame 类型,这是需要进行透视操作的数据集。
values: 单个或多个列名,这些列将被聚合。例如,如果你想要计算某个数值列的总和或平均值,就需要指定这个参数。
index: 单个或多个列名,这些列将作为透视表的行索引。可以是字符串或字符串列表。
columns: 单个或多个列名,这些列将作为透视表的列索引。可以是字符串或字符串列表。
aggfunc: 聚合函数,用于对 values 中的数据进行聚合操作。可以是单个函数(如 np.sum)、字符串(如 'sum')或函数列表。默认为 np.mean。
fill_value: 用于替换缺失值的值,默认为 None。
margins: 布尔值,是否添加所有值的合计行和列。默认为 False。
dropna: 布尔值,是否从结果中删除包含缺失值的行。默认为 True。
margins_name: 合计行和列的名称,默认为 'All'。
observed: 布尔值,是否忽略未观察到的分类。默认为 False。
"""
df = df.pivot_table(index='date', columns='area', values='sales',fill_value=0).reset_index()
print(df)
2. 使用groupby+unstack

优点:提供更大的灵活性,允许你执行更复杂的分组和重塑操作,适合那些超出 pivot_table 能力范围的情况。

缺点:性能取决于具体的数据集和使用的聚合函数。对于非常大的数据集,它可能会因为创建中间结果而消耗更多内存。

import pandas as pd
# 创建示例数据
data = {
    'area': ['North', 'South', 'East', 'West'] * 3,
    'sales': [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120],
    'date': pd.date_range(start='2024-01-01', periods=12)
}
df = pd.DataFrame(data)
# unstack 是 pandas 库中的一个方法,它用于将DataFrame的最内层(默认情况下)或指定层级的行索引转换为列索引,从而将数据从长格式转换为宽格式。这个操作有时也被称为“旋转”或“透视”。unstack通常与groupby一起使用,以实现数据的聚合和重塑。
"""
unstack 参数
level:可以是整数或字符串,指明要转换为列的索引级别。如果是整数,则表示级别编号;如果是字符串,则直接给出级别名称。
fill_value:用于替换新生成的DataFrame中缺失值的对象,默认是NaN。如果你希望用特定值代替缺失值,可以指定这个参数。
"""
df = df.groupby(['date','area'])['sales'].sum().unstack(fill_value=0).reset_index()
print(df)
3. 使用apply()自定义方法

使用apply()方法实现一种类似于SQL中的case when操作,利用case when 的逻辑进行打横,速度非常快,可定制化极高

import pandas as pd
​
​
def split_row_data(row_df, classify):
    """
    自定义函数,按照groupby的分类分割每一行数据
    :param row_df: 会自动传入每一行的dataframe
    :param classify: groupby的类别
    :return:
    """
    if row_df[col_name] == classify:
        return row_df[value_name]
    else:
        return 0
​
# 创建示例数据
data = {
    'area': ['North', 'South', 'East', 'West'] * 3,
    'sales': [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120],
    'date': pd.date_range(start='2024-01-01', periods=12)
}
df = pd.DataFrame(data)
​
​
col_name = 'area'
value_name = 'sales'
col_df = df.groupby(col_name)[value_name].sum()
col_classification = list(col_df.index)
for classification in col_classification:
    # axis=1沿着行方向应用函数
    df[classification] = df.apply(split_row_data, args=(classification,), axis=1)
# 根据需求选择是否保留打横之前的聚合列
new_cols = [col for col in list(df.columns) if col not in [col_name, value_name]]
print(df[new_cols])

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值