如何将带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
相关产品推荐
相关产品推荐

