You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将带MultiIndex的Pandas DataFrame转换为指定格式的Polars DataFrame?

解决方法

方法一:先在Pandas中处理再转Polars

先通过Pandas的melt展平多级索引,再转换为Polars DataFrame:

import pandas as pd
import polars as pl
from pandas import Timestamp

# 原始Pandas DataFrame(使用用户提供的定义)
df = pd.DataFrame.from_dict(
    {
    ('Date', ''): {
        0: Timestamp('2022-04-07 00:00:00'),
        1: Timestamp('2022-04-08 00:00:00'),
        2: Timestamp('2022-04-11 00:00:00'),
        3: Timestamp('2022-04-12 00:00:00'),
        4: Timestamp('2022-04-13 00:00:00')
    },
    ('Adj Close', 'AAPL'): {
        0: 171.10350036621094,
        1: 169.0658416748047,
        2: 164.75196838378906,
        3: 166.65049743652344,
        4: 169.3739776611328
    },
    ('Adj Close', 'SPY'): {
        0: 441.29339599609375,
        1: 440.1134033203125,
        2: 432.5908508300781,
        3: 430.9880065917969,
        4: 435.92437744140625
    },
    ('Close', 'AAPL'): {0: 172.13999938964844, 1: 170.08999633789062, 2: 165.75, 3: 167.66000366210938, 4: 170.39999389648438},
    ('Close', 'SPY'): {0: 448.7699890136719, 1: 447.57000732421875, 2: 439.9200134277344, 3: 438.2900085449219, 4: 443.30999755859375},
    ('High', 'AAPL'): {0: 173.36000061035156, 1: 171.77999877929688, 2: 169.02999877929688, 3: 169.8699951171875, 4: 171.0399932861328},
    ('High', 'SPY'): {0: 450.69000244140625, 1: 450.6300048828125, 2: 445.0, 3: 445.75, 4: 444.1099853515625},
    ('Low', 'AAPL'): {0: 169.85000610351562, 1: 169.1999969482422, 2: 165.5, 3: 166.63999938964844, 4: 166.77000427246094},
    ('Low', 'SPY'): {0: 443.5299987792969, 1: 445.94000244140625, 2: 439.3900146484375, 3: 436.6499938964844, 4: 437.8399963378906},
    ('Open', 'AAPL'): {0: 171.16000366210938, 1: 171.77999877929688, 2: 168.7100067138672, 3: 168.02000427246094, 4: 167.38999938964844},
    ('Open', 'SPY'): {0: 445.5899963378906, 1: 447.9700012207031, 2: 444.1099853515625, 3: 443.0799865722656, 4: 438.0299987792969},
    ('Volume', 'AAPL'): {0: 77594700, 1: 76575500, 2: 72246700, 3: 79265200, 4: 70618900},
    ('Volume', 'SPY'): {0: 78097200, 1: 79272700, 2: 89770500, 3: 84363600, 4: 74070400}
    }
)

# 提取Date列并命名
date_series = df.pop(('Date', '')).rename('Date')

# 展平剩余列的多级索引
melted_pd = df.melt(var_name=['Attribute', 'Ticker'], value_name='Value')

# 合并Date列与展平后的DataFrame
combined_pd = pd.concat([date_series.repeat(len(df.columns) // 2), melted_pd], axis=1)

# 转换为Polars DataFrame
result_pl = pl.from_pandas(combined_pd)

方法二:直接用Polars处理

利用Polars的unpivot方法直接处理多级索引列:

import pandas as pd
import polars as pl
from pandas import Timestamp

# 原始Pandas DataFrame(同上)
df = pd.DataFrame.from_dict(...) # 替换为用户提供的df定义

# 转换为Polars DataFrame
pl_df = pl.from_pandas(df)

# 拆分Date列与其他列
date_col = next(col for col in pl_df.columns if col[0] == 'Date')
other_cols = [col for col in pl_df.columns if col[0] != 'Date']

# 展平多级索引并生成目标格式
result_pl = (
    pl_df
    .select(pl.col(date_col).alias('Date'), *other_cols)
    .unpivot(
        index='Date',
        variable_name=['Attribute', 'Ticker'],
        value_name='Value'
    )
)

结果说明

两种方法最终都会得到符合预期的Polars DataFrame,核心结构如下:

shape: (3012, 4)
┌─────────────────────┬─────────────┬────────┬──────────────────┐
│ Date                ┆ Attribute   ┆ Ticker ┆ Value            │
│ ---                 ┆ ---         ┆ ---    ┆ ---              │
│ datetime[ns]        ┆ str         ┆ str    ┆ f64              │
╞═════════════════════╪═════════════╪════════╪══════════════════╡
│ 2022-04-07 00:00:00 ┆ Adj Close   ┆ AAPL   ┆ 171.103500366211 │
│ 2022-04-08 00:00:00 ┆ Adj Close   ┆ AAPL   ┆ 169.065841674805 │
│ 2022-04-11 00:00:00 ┆ Adj Close   ┆ AAPL   ┆ 164.751968383789 │
│ ...                 ┆ ...         ┆ ...    ┆ ...              │
│ 2023-04-06 00:00:00 ┆ Volume      ┆ SPY    ┆ 63575700.0       │
└─────────────────────┴─────────────┴────────┴──────────────────┘

内容的提问来源于stack exchange,提问作者codedancer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 16:04:58