我已经读过pandas: how to run a pivot with a multi-index?,但无法解决我的问题。
给出以下数据框:
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"]
})
我想扩展test
列,使用result
中的值,并忽略ref
。换句话说,所需的输出如下:
date id a b c d e f
0 20180920 A123456789 70 90 110 (-) (+) 0.3
所以我尝试了df.pivot(index=["date", "id"], columns="test", values="result")
,但是它失败了,并出现 ValueError:传递的值的长度为6,索引表示2 。我认为这与“如果传递数组,它必须与数据长度相同”有关。在pivot_table
documentation中,但我只是不明白它的含义。有人可以详细说明吗?
顺便说一句,我终于通过df.drop(columns="ref").set_index(["date", "id", "test"]).unstack(level=2)
得到了想要的输出。这是唯一正确的方法吗?
答案 0 :(得分:4)
pivot不接受列列表作为索引,因此您需要使用ivot_table。在这里,使用first进行的聚合是假设没有重复项。
pd.pivot_table(df,index=["date", "id"], columns="test", values="result", aggfunc= 'first')\
.reset_index().rename_axis(None, 1)
按照@piRsquared的建议使用set_index并取消堆叠和重命名轴会更安全,
df.set_index(['date', 'id', 'test']).result.unstack()\
.reset_index().rename_axis(None, 1)
无论哪种方式,
date id a b c d e f
20180920 A123456789 70 90 110 (-) (+) 0.3
答案 1 :(得分:4)
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
关于文档,您可以检查issue 16578,而在熊猫中0.24.0应该是improved docs还是对使用MultiIndex
的新支持? issue 8160也有点不清楚。
我认为您的最后一个代码应该只进行了一点改进(与@Vaishali相同的解决方案)-通过在Series with MultiIndex
之后进行选择来创建set_index
,并为unstack
删除level
,因为默认情况下是未堆叠的MultiIndex的最后一级-Series.unstack
:
级别:整数,字符串或这些列表,默认为最后一个级别
要取消堆叠的等级,可以通过等级名称
#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)
答案 2 :(得分:0)
使用在pandas/issues/23955中定义的功能
def multiindex_pivot(df, columns=None, values=None):
#https://github.com/pandas-dev/pandas/issues/23955
names = list(df.index.names)
df = df.reset_index()
list_index = df[names].values
tuples_index = [tuple(i) for i in list_index] # hashable
df = df.assign(tuples_index=tuples_index)
df = df.pivot(index="tuples_index", columns=columns, values=values)
tuples_index = df.index # reduced
index = pd.MultiIndex.from_tuples(tuples_index, names=names)
df.index = index
return df
multiindex_pivot(df.set_index(['date', 'id']), columns='test', values='result')
Out[10]:
test a b c d e f
date id
20180920 A123456789 70 90 110 (-) (+) 0.3