【问题标题】:Sorting the order of bars in pandas/matplotlib bar plots对 pandas/matplotlib 条形图中的条形顺序进行排序
【发布时间】:2014-05-03 07:51:09
【问题描述】:

什么是 Pythonic/pandas 对 pandas 列中的“级别”进行排序以在条形图中给出特定条形顺序的方式。

例如,给定:

import pandas as pd
df = pd.DataFrame({
    'group': ['a', 'a', 'a', 'a', 'a', 'a', 'a', 
              'b', 'b', 'b', 'b', 'b', 'b', 'b'],
    'day': ['Mon', 'Tues', 'Fri', 'Thurs', 'Sat', 'Sun', 'Weds',
            'Fri', 'Sun', 'Thurs', 'Sat', 'Weds', 'Mon', 'Tues'],
    'amount': [1, 2, 4, 2, 1, 1, 2, 4, 5, 3, 4, 2, 1, 3]})
dfx = df.groupby(['group'])
dfx.plot(kind='bar', x='day')

我可以生成以下一对图:

条形的顺序遵循行顺序。

对数据重新排序以使条形图的条形按周一至周日排列的最佳方式是什么?

更新:这个垃圾解决方案有效 - 但它使用额外的排序列的方式远非优雅:

df2 = pd.DataFrame({
    'day': ['Mon', 'Tues', 'Weds', 'Thurs', 'Fri', 'Sat', 'Sun'],
    'num': [0, 1, 2, 3, 4, 5, 6]})
df = pd.merge(df, df2, on='day')
df = df.sort_values('num')
dfx = df.groupby(['group'])
dfx.plot(kind='bar', x='day')

进一步概括:

是否有一种解决方案也可以修复“闪避”条形图中的条形顺序:

df.pivot('day', 'group', 'amount').plot(kind='bar')

【问题讨论】:

    标签: python matplotlib pandas


    【解决方案1】:

    您必须提供一个映射来指定如何对日期名称进行排序。 (如果它们被存储为正确的日期,那么还有其他方法可以做到这一点。)

    更新:

    构建密钥。你可以明确地写出一本字典,或者使用一些聪明的东西,比如这个字典理解。

    weekdays = ['Mon', 'Tues', 'Weds', 'Thurs', 'Fri', 'Sat', 'Sun']
    mapping = {day: i for i, day in enumerate(weekdays)}
    key = df['day'].map(mapping)
    

    而且排序很简单:

    df.iloc[key.argsort()]
    

    【讨论】:

    • 我想多了。您只需要key 和上面的简单单行。
    • 不需要 df=df.iloc[key.argsort()] 吗?
    • 这取决于您是否希望您的解决方案覆盖df 或成为新变量,例如df1。我把它留给你了。
    • 好的 - 谢谢;那么,如果我用 df.pivot('day','group','amount').plot(kind='bar') 躲避绘图,排序如何工作?订单丢失?
    • Dan - 将字典理解作为 map() 排序的基础是一个非常有用的技巧;感谢您添加它:-)
    【解决方案2】:

    我知道这个回复很晚,但是对于所提出的两种情况的简单解决方案,不使用字典/映射就像我在下面发布的那样。

    将 'day' 设置为索引使您可以使用 .loc 以特定顺序选择数据

    1) 对于两个独立的地块

    df=pd.DataFrame({'group':['a','a','a','a','a','a','a','b','b','b','b','b','b','b'],
         'day':['Mon','Tues','Fri','Thurs','Sat','Sun','Weds','Fri','Sun','Thurs','Sat','Weds','Mon','Tues'],
         'amount':[1,2,4,2,1,1,2,4,5,3,4,2,1,3]})
    
    order = ['Mon', 'Tues', 'Weds','Thurs','Fri','Sat','Sun']`
    df.set_index('day').loc[order].groupby('group').plot(kind='bar')
    

    2) 对于带有闪避图的枢轴示例:

    order = ['Mon', 'Tues', 'Weds','Thurs','Fri','Sat','Sun']
    df.pivot('day','group','amount').loc[order].plot(kind='bar')
    

    请注意,pivot 导致 day 已经在索引中,因此您可以在此处再次使用 .loc。

    编辑:最好在这些解决方案中使用 .loc 而不是 .ix,当列名和索引是数字时,.ix 将被弃用,并且可能会产生奇怪的结果。

    【讨论】:

    • 闪避情节的第二个例子对我来说效果很好。谢谢!
    【解决方案3】:

    我将提供以下代码来扩展 Dan 的答案,以解决 OP 问题的“进一步概括”部分。首先,一个基于 Dan 解决方案的简单案例(只有一个变量)的完整示例:

    import pandas as pd
    
    # Create dataframe 
    df=pd.DataFrame({
        'group':['a','a','a','a','a','a','a','b','b','b','b','b','b','b'],
        'day':['Mon','Tues','Fri','Thurs','Sat','Sun','Weds','Fri','Sun','Thurs','Sat','Weds','Mon','Tues'],
        'amount':[1,2,4,2,1,1,2,4,5,3,4,2,1,3]
    })
    
    
    # Calculate the total amount for each day
    df_grouped = df.groupby(['day']).sum().amount.reset_index()
    
    # Use Dan's trick to order days names in the table created by groupby
    weekdays = ['Mon', 'Tues', 'Weds', 'Thurs', 'Fri', 'Sat', 'Sun']
    mapping = {day: i for i, day in enumerate(weekdays)}
    key = df_grouped['day'].map(mapping)    
    df_grouped = df_grouped.iloc[key.argsort()]
    
    # Draw the bar chart
    df_grouped.plot(kind='bar', x='day')
    

    现在,我们使用相同的排序技术对数据透视表的行进行排序(而不是 groupby 创建的行)。

    import pandas as pd
    
    # Create dataframe 
    df=pd.DataFrame({
        'group':['a','a','a','a','a','a','a','b','b','b','b','b','b','b'],
        'day':['Mon','Tues','Fri','Thurs','Sat','Sun','Weds','Fri','Sun','Thurs','Sat','Weds','Mon','Tues'],
        'amount':[1,2,4,2,1,1,2,4,5,3,4,2,1,3]
    })
    
    # Get the amount for each day AND EACH GROUP
    df_grouped = df.groupby(['group', 'day']).sum().amount.reset_index()
    
    # Create pivot table to get the total amount for each day and each in the proper format to plot multiple series with pandas
    df_pivot = df_grouped.pivot('day','group','amount').reset_index()
    
    # Use Dan's trick to order days names in the table created by PIVOT (not the table created by groupby, in the previous example)
    weekdays = ['Mon', 'Tues', 'Weds', 'Thurs', 'Fri', 'Sat', 'Sun']
    mapping = {day: i for i, day in enumerate(weekdays)}
    key = df_pivot['day'].map(mapping)    
    df_pivot = df_pivot.iloc[key.argsort()]
    
    # Draw the bar chart
    df_pivot.plot(kind='bar', x='day')
    

    结果如下图:

    【讨论】:

      猜你喜欢
      • 2014-10-02
      • 2017-12-06
      • 2013-12-31
      • 2015-03-17
      • 2022-08-23
      • 1970-01-01
      • 2022-01-17
      • 2020-09-01
      • 1970-01-01
      相关资源
      最近更新 更多