【问题标题】:Create new columns based on rank order in Pandas根据 Pandas 中的排名顺序创建新列
【发布时间】:2021-06-16 03:02:10
【问题描述】:

我有一个这样的数据框,

ID  Hour    Prob       Rank
  
 123  10     0.4         4
 123  11     0.6         3
 123  12     1.0         1
 123  13     0.9         2
 456  10     0.8         1
 456  11     0.5         2
 456  12     0.1         4
 456  13     0.2         3

我正在尝试基于此创建一个数据框,应该像这样,

  ID  Rank_1  Rank_2  Rank_3  Rank_4 Prob_1  Prob_2  Prob_3  Prob_4

  123   12      13      11      10     1.0     0.9     0.6     0.4
  456   10      11      13      12     0.8     0.5     0.2     0.1

我对 R 中的 tidyverse 之类的 pandas 不是很熟悉。非常感谢任何帮助。提前致谢。

【问题讨论】:

    标签: python pandas


    【解决方案1】:
    df = df.set_index(["ID", "Rank"])
    df = df.unstack("Rank")
    df.columns = df.columns.map(lambda col: "_".join(map(str, col)))
    

    我们首先将IDRank 带到索引侧,然后将Rank 取消堆叠到列。然后加入列名HourProb 已经存在的行列给出

         Hour_1  Hour_2  Hour_3  Hour_4  Prob_1  Prob_2  Prob_3  Prob_4
    ID
    123      12      13      11      10     1.0     0.9     0.6     0.4
    456      10      11      13      12     0.8     0.5     0.2     0.1
    

    但由于您再次需要Rank 而不是Hour,我们最后这样做:

    df.columns = df.columns.str.replace("Hour", "Rank")
    

    得到

    >>> df
    
         Rank_1  Rank_2  Rank_3  Rank_4  Prob_1  Prob_2  Prob_3  Prob_4
    ID
    123      12      13      11      10     1.0     0.9     0.6     0.4
    456      10      11      13      12     0.8     0.5     0.2     0.1
    

    如果unstack 参数中有重复条目(即此处为Rank),我们可以在设置索引时append。然后重复的问题就会消失,但会出现很多NaNs:

    >>> df   # 2nd rows rank was made 4 for duplication
    
    ID  Hour    Prob       Rank
      
     123  10     0.4         4
     123  11     0.6         4
     123  12     1.0         1
     123  13     0.9         2
     456  10     0.8         1
     456  11     0.5         2
     456  12     0.1         4
     456  13     0.2         3
    
    # same operations, *except* `append=True`
    >>> df = df.set_index(["ID", "Rank"], append=True)
    >>> df = df.unstack("Rank")
    >>> df.columns = df.columns.map(lambda col: "_".join(map(str, col)))
    >>> df.columns = df.columns.str.replace("Hour", "Rank")
    >>> df
    
           Rank_1  Rank_2  Rank_3  Rank_4  Prob_1  Prob_2  Prob_3  Prob_4
      ID
    0 123     NaN     NaN     NaN    10.0     NaN     NaN     NaN     0.4
    1 123     NaN     NaN     NaN    11.0     NaN     NaN     NaN     0.6
    2 123    12.0     NaN     NaN     NaN     1.0     NaN     NaN     NaN
    3 123     NaN    13.0     NaN     NaN     NaN     0.9     NaN     NaN
    4 456    10.0     NaN     NaN     NaN     0.8     NaN     NaN     NaN
    5 456     NaN    11.0     NaN     NaN     NaN     0.5     NaN     NaN
    6 456     NaN     NaN     NaN    12.0     NaN     NaN     NaN     0.1
    7 456     NaN     NaN    13.0     NaN     NaN     NaN     0.2     NaN
    

    现在pivot_table 可以聚合这些;假设我们想对重复项中的值求和:

    >>> df.pivot_table(index="ID", aggfunc="sum")
    
         Prob_1  Prob_2  Prob_3  Prob_4  Rank_1  Rank_2  Rank_3  Rank_4
    ID
    123     1.0     0.9     0.0     1.0    12.0    13.0     0.0    21.0
    456     0.8     0.5     0.2     0.1    10.0    11.0    13.0    12.0
    
    

    请注意,ID 没有任何重复的结果是相同的;对于另一个,不存在的等级 3 为 0;以及排名 4 的值的总和。

    【讨论】:

    • 非常感谢。我在具有数十万个 ID 的数据集上尝试了此操作,但收到此错误“ValueError:索引包含重复条目,无法重塑”。你能告诉我如何处理这个吗?我在代码的第二行收到该错误 - df = df.unstack("Rank")
    • 嗨@Raju。这意味着Rank 列的每个 ID 都有重复项。这是可取的吗?你将如何处理输出中的那些?例如,如果 ID 123 排名 3 两次。
    • @Raju 编辑了重复情况的答案,希望对您有所帮助。
    • 谢谢。我认为在基于 Prob 列创建排名时,我在上一步中犯了一个错误。我看到我在 Prob 中有很多重复项。我想我应该在此之前处理它。
    【解决方案2】:

    您可以在 python 中使用tidyverse 方式使用datar

    >>> from datar.all import f, tribble, pivot_wider, rename_with
    >>> 
    >>> df = tribble(
    ...     f.ID,  f.Hour,  f.Prob,  f.Rank,
    ...     123,   10,      0.4,     4,
    ...     123,   11,      0.6,     3,
    ...     123,   12,      1.0,     1,
    ...     123,   13,      0.9,     2,
    ...     456,   10,      0.8,     1,
    ...     456,   11,      0.5,     2,
    ...     456,   12,      0.1,     4,
    ...     456,   13,      0.2,     3,
    ... )
    >>> 
    >>> df >> pivot_wider(
    ...     names_from=f.Rank, 
    ...     values_from=[f.Hour, f.Prob], 
    ...     names_glue='{_value}_{Rank}'
    ... ) >> rename_with(
    ...     lambda col: col.replace('Hour', 'Rank')
    ... )
           ID  Rank_1  Rank_2  Rank_3  Rank_4    Prob_1    Prob_2    Prob_3    Prob_4
      <int64> <int64> <int64> <int64> <int64> <float64> <float64> <float64> <float64>
    0     123      12      13      11      10       1.0       0.9       0.6       0.4
    1     456      10      11      13      12       0.8       0.5       0.2       0.1
    

    我是datar 包的作者。如果您有任何问题,请随时提交问题。

    【讨论】:

      猜你喜欢
      • 2021-12-26
      • 2021-09-30
      • 2015-03-24
      • 1970-01-01
      • 2023-02-02
      • 2020-07-29
      • 2018-07-25
      • 2020-04-25
      • 2017-02-13
      相关资源
      最近更新 更多