解冻Pandas DataFrame

36

我有一个带有两个ID变量的pandas数据框:

df = pd.DataFrame({'id': [1,1,1,2,2,3], 
               'num': [10,10,12,13,14,15],
               'q': ['a', 'b', 'd', 'a', 'b', 'z'],
               'v': [2,4,6,8,10,12]})

   id  num  q   v
0   1   10  a   2
1   1   10  b   4
2   1   12  d   6
3   2   13  a   8
4   2   14  b  10
5   3   15  z  12

我可以使用以下代码旋转表格:

df.pivot('id','q','v')

最后得到类似这样的东西:

q    a   b   d   z
id                
1    2   4   6 NaN
2    8  10 NaN NaN
3  NaN NaN NaN  12

然而,我真正想要的是(未熔化的原始形式):

id   num   a   b   d   z               
1    10   2   4 NaN NaN
1    12 NaN NaN   6 NaN  
2    13   8 NaN NaN NaN
2    14 NaN  10 NaN NaN
3    15 NaN NaN NaN  12

换句话说:

  1. 'id'和'num'是我的索引(通常情况下,我只看到'id'或'num'是索引,但我需要两者都是索引,因为我尝试检索原始的未融合形式)
  2. 'q'是我的列
  3. 'v'是表中的值

更新

我在Wes McKinney的博客中找到了一个相近的解决方案:

df.pivot_table(index=['id','num'], columns='q')

         v            
q        a   b   d   z
id num                
1  10    2   4 NaN NaN
   12  NaN NaN   6 NaN
2  13    8 NaN NaN NaN
   14  NaN  10 NaN NaN
3  15  NaN NaN NaN  12

然而,该格式与我上面所想要的格式有些不同。

6个回答

42

你可以使用 set_indexunstack

In [18]: df.set_index(['id', 'num', 'q'])['v'].unstack().reset_index()
Out[18]:
q  id  num    a     b    d     z
0   1   10  2.0   4.0  NaN   NaN
1   1   12  NaN   NaN  6.0   NaN
2   2   13  8.0   NaN  NaN   NaN
3   2   14  NaN  10.0  NaN   NaN
4   3   15  NaN   NaN  NaN  12.0

2
这比被接受的答案干净多了。谢谢! - kev8484
谢谢。pandas.pivot() 函数在使用多个索引列时并不像我希望的那样直接,但这个解决方案却奏效了。 - Dan Jarratt
pivot_table 将整数转换为浮点数。但现在不再这样。谢谢! - ProGirlXOXO
1
你可以使用以下代码来删除“q”:del df2.columns.name - Walker Hale IV

25

你离成功很近了,只需要将列索引重命名为“None”,你就可以得到想要的结果。

df2 = df.pivot_table(index=['id','num'], columns='q')
df2.columns = df2.columns.droplevel().rename(None)
df2.reset_index().fillna("null").to_csv("test.csv", sep="\t", index=None)

请注意,默认情况下,“v”列应为数字,以便进行聚合。否则,Pandas将出现错误:
DataError: No numeric types to aggregate

解决方法是使用自定义lambda函数指定你自己的聚合函数:

df2 = df.pivot_table(index=['id','num'], columns='q', aggfunc= lambda x: x)

啊,我就差一点了!我知道它与 df.columns.name 有关,但是无法弄清如何适当地使用 rename。感谢您的帮助! - slaw
11
重要提示:“close slaw”听起来像“coleslaw”。 - Dance Party2

4

您可以删除名称q。

df1.columns=df1.columns.tolist()

零的答案加上去掉q的结果为:
df1 = df.set_index(['id', 'num', 'q'])['v'].unstack().reset_index()
df1.columns=df1.columns.tolist()

   id  num    a     b    d     z
0   1   10  2.0   4.0  NaN   NaN
1   1   12  NaN   NaN  6.0   NaN
2   2   13  8.0   NaN  NaN   NaN
3   2   14  NaN  10.0  NaN   NaN
4   3   15  NaN   NaN  NaN  12.0

2

这可能完全可行:

  1. 数据透视表

df2 = (df.pivot_table(index=['id', 'num'], columns='q', values='v')).reset_index()

  1. 将第一层列名与第二层连接起来

df2.columns =[s1 + str(s2) for (s1,s2) in df2.columns.tolist()]


1
想出了一个接近的解决方案。
df2 = df.pivot_table(index=['id','num'], columns='q')
df2.columns = df2.columns.droplevel()
df2.reset_index().fillna("null").to_csv("test.csv", sep="\t", index=None)

仍然无法弄清如何从数据框中删除“q”。

0

这可以分为三个步骤完成:

#1: Prepare auxilary column 'id_num': 
df['id_num'] = df[['id', 'num']].apply(tuple, axis=1)
df = df.drop(columns=['id', 'num'])

#2: 'pivot' is almost an inverse of melt:
df, df.columns.name = df.pivot(index='id_num', columns='q', values='v').reset_index(), ''

#3: Bring back 'id' and 'num' columns:
df['id'], df['num'] = zip(*df['id_num'])
df = df.drop(columns=['id_num'])

这是一个结果,但列的顺序不同:

     a     b    d     z  id  num
0  2.0   4.0  NaN   NaN   1   10
1  NaN   NaN  6.0   NaN   1   12
2  8.0   NaN  NaN   NaN   2   13
3  NaN  10.0  NaN   NaN   2   14
4  NaN   NaN  NaN  12.0   3   15

或者按照正确的顺序:

def multiindex_pivot(df, columns=None, values=None):
    #inspired by: 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
    df = df.reset_index() #me
    df.columns.name = ''  #me
    return df

df = df.set_index(['id', 'num'])
df = multiindex_pivot(df, columns='q', values='v')

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