【问题标题】:Pandas: Pivoting with multi-index dataPandas:使用多索引数据进行透视
【发布时间】:2013-10-17 08:11:07
【问题描述】:

我有两个如下所示的数据框:

rating
   BMW  Fiat  Toyota
0    7     2       3
1    8     1       8
2    9    10       7
3    8     3       9

own
   BMW  Fiat  Toyota
0    1     1       0
1    0     1       1
2    0     0       1
3    0     1       1

我最终试图获得 brandusagemean rating 数据透视表。或者是这样的:

            BMW  Fiat  Toyota
Usage                        
0      8.333333    10       3
1      7.000000     2       8

我的方法是像这样合并数据集:

Measure  Rating                Own              
Brand       BMW  Fiat  Toyota  BMW  Fiat  Toyota
0             7     2       3    1     1       0
1             8     1       8    0     1       1
2             9    10       7    0     0       1
3             8     3       9    0     1       1

然后尝试使用 rating 作为值、own 作为行、brand 作为列来创建数据透视表。但我一直在处理关键问题。我也尝试过拆分度量级别或品牌级别,但我似乎无法使用行索引名称作为枢轴键。

我做错了什么?有更好的方法吗?

【问题讨论】:

    标签: python pandas pivot-table


    【解决方案1】:

    我不是 Pandas 专家,因此解决方案可能比您想要的更笨拙,但是:

    rating = pd.DataFrame({"BMW":[7, 8, 9, 8], "Fiat":[2, 1, 10, 3], "Toyota":[3, 8, 7,9]})
    own = pd.DataFrame({"BMW":[1, 0, 0, 0], "Fiat":[1, 1, 0, 1], "Toyota":[0, 1, 1, 1]})
    
    r = rating.unstack().reset_index(name='value')
    o = own.unstack().reset_index(name='value')
    res = DataFrame({"Brand":r["level_0"], "Rating": r["value"], "Own": o["value"]})
    res = res.groupby(["Own", "Brand"]).mean().reset_index()
    res.pivot(index="Own", columns="Brand", values="Rating")
    
    # result
    # Brand       BMW  Fiat  Toyota
    # Own                          
    # 0      8.333333    10       3
    # 1      7.000000     2       8
    

    另一种解决方案,虽然不是很通用(您可以使用 for 循环,但您必须知道 own 数据帧中有哪些值):

    d = []
    for o in (0, 1):
        t = rating[own == o]
        t["own"] = o
        d.append(t)
    
    res = pd.concat(d).groupby("own").mean()
    

    【讨论】:

    • 谢谢。很高兴有一个解决方案。你说得对,我希望有更优雅的东西,但一个解决方案让我解脱了。我总是可以写一个函数。
    • @Brendon 我现在正努力花尽可能多的时间来学习 Pandas,一两周后我会看看我能做什么:) 请不要接受答案,可能是一些大师将带来超优雅的解决方案
    • 好吧,您个人资料上的标语说明了很多:)。我将推迟一周再接受你的回答。再次感谢。
    • @Brendon 看看,我添加了另一种解决方案,我认为是更 Python 的解决方案。如果我知道如何就地向 DataFrame 添加列,它可能会更短
    【解决方案2】:

    我对自己的问题有了新的答案(基于 Roman 的初始答案)。关键是要获得所需维度的索引。例如

    rating.columns.names = ["Brand"]
    rating.index.names = ["n"]
    print rating
    
    Brand  BMW  Fiat  Toyota
    n                       
    0        7     2       3
    1        8     1       8
    2        9    10       7
    3        8     3       9
    
    own.columns.names = ["Brand"]
    own.index.names = ["n"]
    print own
    
    Brand  BMW  Fiat  Toyota
    n                       
    0        1     1       0
    1        0     1       1
    2        0     0       1
    3        0     1       1
    
    merged = pd.merge(own.unstack().reset_index(name="Own"), 
                      rating.unstack().reset_index(name="Rating"))
    print merged
    
         Brand  n  Own  Rating
    0      BMW  0    1       7
    1      BMW  1    0       8
    2      BMW  2    0       9
    3      BMW  3    0       8
    4     Fiat  0    1       2
    5     Fiat  1    1       1
    6     Fiat  2    0      10
    7     Fiat  3    1       3
    8   Toyota  0    0       3
    9   Toyota  1    1       8
    10  Toyota  2    1       7
    11  Toyota  3    1       9
    

    那么很容易使用pivot_table命令把它变成想要的结果:

    print merged.pivot_table(rows="Brand", cols="Own", values="Rating")
    
    Own             0  1
    Brand               
    BMW      8.333333  7
    Fiat    10.000000  2
    Toyota   3.000000  8
    

    这就是我一直在寻找的。再次感谢 Roman 指路。

    【讨论】:

      猜你喜欢
      • 2023-03-29
      • 2016-05-26
      • 1970-01-01
      • 2016-09-15
      • 2020-08-31
      • 2017-08-19
      • 1970-01-01
      • 2020-08-30
      相关资源
      最近更新 更多