Pandas将列转换为MultiIndex

3
我怎样将这个混合了字符串和整数的 DataFrame 的第一列转化?
df = pd.DataFrame(
    [
        ["title1", "a", "b", "c", "d"],
        [1, 2, 3, 4, 5],
        [10, 2, 3, 4, 5],
        [100, 2, 3, 4, 5],
        ["title2", "a", "b", "c", "d"],
        [1, 2, 3, 4, 5],
        [10, 2, 3, 4, 5],
        [100, 2, 3, 4, 5],
        ["title3", "a", "b", "c", "d"],
        [1, 2, 3, 4, 5],
        [10, 2, 3, 4, 5],
        [100, 2, 3, 4, 5],
    ]
)

看起来像这样。
title1  a   b   c   d
1       2   3   4   5
10      2   3   4   5
100     2   3   4   5
title2  a   b   c   d
1       2   3   4   5
10      2   3   4   5
100     2   3   4   5
title3  a   b   c   d
1       2   3   4   5
10      2   3   4   5
100     2   3   4   5

将字符串放在第一级别,整数放在第二级别,将其转换为具有多层索引的MultiIndex对象?
            a   b   c   d
title1  1   2   3   4   5
        10  2   3   4   5
        100 2   3   4   5
title2  1   2   3   4   5
        10  2   3   4   5
        100 2   3   4   5
title3  1   2   3   4   5
        10  2   3   4   5
        100 2   3   4   5

实际数据中的值a、b、c、d在每一行中都相同吗? - jezrael
1
@jezrael 是的,它们是完全相同的。 - Janosh
太好了,所以答案应该很好用。 - jezrael
2个回答

3

使用:

#get mask for distingusih strings values in column 0
m = pd.to_numeric(df[0], errors='coerce').isna()
#alternative
#m = ~df[0].astype(str).str.isnumeric()
#create new column 0 filled with strings
df.insert(0, 'a', df[0].where(m).ffill())
#mask for filter not same values in both columns
m1 = df['a'].ne(df[0])
#create MultiIndex
df = df.set_index(['a', 0])
#assign new columns names by first row
df.columns = df.iloc[0]
#filter out by mask and remove index, columns names
df = df[m1.values].rename_axis((None, None)).rename_axis(None, axis=1)
print (df)
            a  b  c  d
title1 1    2  3  4  5
       10   2  3  4  5
       100  2  3  4  5
title2 1    2  3  4  5
       10   2  3  4  5
       100  2  3  4  5
title3 1    2  3  4  5
       10   2  3  4  5
       100  2  3  4  5

我该如何命名这两个索引列以显示,比如在标题上方显示“i1”,在“[1,10,100]”上方显示“i2”? - Janosh
1
@Casimir - 将 .rename_axis((None, None)) 更改为 .rename_axis(('i1', 'i2')) - jezrael

1
这类问题的关键是创建一个布尔序列,以识别 level_0 索引的位置。

mask = df[1].str.contains('a')   # Identify the rows containing the level_0 multiindex

header = df.loc[0,1:4].to_list()   # Get header list

df[-1] = df[0].where(mask).ffill()   # Create a seperate level_0 column

result = (df[~mask.fillna(False)]
            .set_index([-1,0])
            .astype(int)
            .rename_axis([None,None])
            .set_axis(header,axis=1,inplace=False))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接