尝试在DataFrame.pivot中具有多索引时发生ValueError

ytu*_*ytu 5 python pivot dataframe pandas

我读过熊猫:如何使用多索引运行数据透视?但这不能解决我的问题。

给定以下数据框:

import pandas as pd
df = pd.DataFrame({
    "date": ["20180920"] * 6,
    "id": ["A123456789"] * 6,
    "test": ["a", "b", "c", "d", "e", "f"],
    "result": [70, 90, 110, "(-)", "(+)", 0.3],
    "ref": ["< 90", "70 - 100", "100 - 120", "(-)", "(-)", "< 1"]
})
Run Code Online (Sandbox Code Playgroud)

我想散布该test列,使用中的值result,然后忽略ref。换句话说,所需的输出如下:

       date          id      a   b    c    d    e    f
0  20180920  A123456789     70  90  110  (-)  (+)  0.3
Run Code Online (Sandbox Code Playgroud)

因此,我尝试了一下df.pivot(index=["date", "id"], columns="test", values="result"),但由于ValueError失败:传递的值的长度为6,索引隐含2。我认为这与“如果传递数组,它必须与数据长度相同”有关。在pivot_table文档中,但我只是不明白它的含义。有人可以详细说明吗?

顺便说一句,我终于通过获得了所需的输出df.drop(columns="ref").set_index(["date", "id", "test"]).unstack(level=2)。这是唯一正确的方法吗?

jez*_*ael 10

pivot 可以使用,但代码有点疯狂:

df = (df.set_index(["date", "id"])
        .pivot(columns="test")['result']
        .reset_index()
        .rename_axis(None, axis=1)
     )
print (df)

       date          id   a   b    c    d    e    f
0  20180920  A123456789  70  90  110  (-)  (+)  0.3
Run Code Online (Sandbox Code Playgroud)

关于文档,您可以检查问题 16578并且在 Pandas 0.24.0 中应该改进文档或者可能对使用的新支持MultiIndex?从issue 8160也有点不清楚。

在我看来,您的最后一个代码应该只改进一点(与@Vaishali 相同的解决方案)-Series with MultiIndex通过选择 afterset_index和 for unstackremove来创建level,因为默认情况下是未堆叠的 MultiIndex 的最后一级- Series.unstack

level : int, string, or list of these, default last level

要取消堆叠的级别,可以传递级别名称

#all 3 return same output
df.set_index(["date", "id", "test"])['result'].unstack()
df.set_index(["date", "id", "test"])['result'].unstack(level=2)
df.set_index(["date", "id", "test"])['result'].unstack(level=-1)
Run Code Online (Sandbox Code Playgroud)


Vai*_*ali 5

ivot不接受列列表作为索引,因此您需要使用ivot_table。在这里,使用first进行的聚合是假设没有重复项。

pd.pivot_table(df,index=["date", "id"], columns="test", values="result", aggfunc= 'first')\
.reset_index().rename_axis(None, 1)
Run Code Online (Sandbox Code Playgroud)

按照@piRsquared的建议使用set_index以及unstack和named_axis会更安全,

df.set_index(['date', 'id', 'test']).result.unstack()\
.reset_index().rename_axis(None, 1)
Run Code Online (Sandbox Code Playgroud)

无论哪种方式,

    date    id          a   b   c   d   e   f
20180920    A123456789  70  90  110 (-) (+) 0.3
Run Code Online (Sandbox Code Playgroud)