【问题标题】:Python - Pivot and create histograms from Pandas column, with missing valuesPython - 从 Pandas 列中透视并创建直方图,缺少值
【发布时间】:2018-09-16 12:05:09
【问题描述】:

具有以下数据框:

   name  value  count  total_count
0     A      0      1           20
1     A      1      2           20
2     A      2      2           20
3     A      3      2           20
4     A      4      3           20
5     A      5      3           20
6     A      6      2           20
7     A      7      2           20
8     A      8      2           20
9     A      9      1           20
----------------------------------
10    B      0     10           75
11    B      5     30           75
12    B      6     20           75
13    B      8     10           75
14    B      9      5           75

我想对数据进行透视,按名称值对每一行进行分组,然后根据聚合到 bin 中的值和计数列创建列。

说明:我有 10 个可能的值,范围 0-9,并非所有值都存在于每个组中。在上面的示例中,组 B 缺少值 1、2、3、4、7。我想创建一个包含 5 个 bin 的直方图,忽略缺失值并计算每个 bin 的计数百分比。所以结果会是这样的:

  name       0-1  2-3  4-5  6-7       8-9
0    A  0.150000  0.2  0.3  0.2  0.150000
1    B  0.133333  0.0  0.4  0.4  0.066667

例如,对于组 A 的 bin 0-1,计算是值 0,1 (1+2) 的计数总和除以 total_countA

  name       0-1
0    A       (1+2)/20 = 0.15

我一直在研究 hist methodthis StackOverflow question,但仍在努力找出正确的方法。

【问题讨论】:

    标签: python pandas pivot-table histogram


    【解决方案1】:

    使用pd.cut 对您的功能进行分箱,然后使用df.groupby().count().unstack() 方法获取您正在寻找的数据框。在 group by 期间,您可以使用任何聚合函数(.sum()、.count() 等)来获得您正在寻找的结果。如果您正在寻找示例,则下面的代码有效。

    import pandas as pd
    import numpy as np
    
    df = pd.DataFrame(
        data ={'name': ['Group A','Group B']*5,
               'number': np.arange(0,10), 
               'value': np.arange(30,40)})
    df['number_bin'] = pd.cut(df['number'], bins=np.arange(0,10))
    # Option 1: Sums
    df.groupby(['number_bin','name'])['value'].sum().unstack(0)
    # Options 2: Counts
    df.groupby(['number_bin','name'])['value'].count().unstack(0)
    

    原始数据中的空值不会影响结果。

    【讨论】:

      【解决方案2】:

      要获得确切的结果,您可以试试这个。

      bins=range(10)
      res = df.groupby('name')['count'].sum()
      intervals = pd.cut(df.value, bins=bins, include_lowest=True)
      df1 = (df.groupby([intervals,"name"])['count'].sum()/res).unstack(0)
      
      df1.columns = df1.columns.astype(str)  # convert the cols to string
      df1.columns = ['a','b','c','d','e','f','g','h','i']  # rename the cols
      cols = ['a',"b","d","f","h"]
      
      df1 = df1.add(df1.iloc[:,1:].shift(-1, axis=1), fill_value=0)[cols]
      print(df1)
      

      您可以稍后手动重命名列。

      # Output:
                 a         b     d        f        h 
      name                    
         A    0.150000    0.2   0.3   0.200000    0.15
         B    0.133333    NaN   0.4   0.266667    0.20
      

      您可以使用 df1.fillna("0.0") 替换 NaN

      【讨论】:

      • 轰隆隆!这就是我一直在寻找的
      • @ShlomiSchwartz 乐于助人。 :)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多