【问题标题】:Pandas enumerate groups in descending orderPandas 按降序枚举组
【发布时间】:2019-06-23 23:21:56
【问题描述】:

我有以下列:

   column
0      10
1      10
2       8
3       8
4       6
5       6

我的目标是找到今天的唯一值(在本例中为 3)并创建一个新列,该列将创建以下内容

   new_column
0           3
1           3
2           2
3           2
4           1
5           1

编号从唯一值的长度 (3) 开始,如果当前行与基于原始列的上一行相同,则重复相同的编号。随着行值的变化,数字会减少。原始列中的所有唯一值都具有相同的行数(在这种情况下,每个唯一值有 2 行)。

我的解决方案是按原始列分组并创建一个新列表,如下所示:

i=1
new_time=[]
for j, v in df.groupby('column'):
    new_time.append([i]*2)
    i=i+1

然后我会按降序展平列表排序。还有其他更简单的解决方案吗?

谢谢。

【问题讨论】:

    标签: python pandas dataframe group-by pandas-groupby


    【解决方案1】:

    pd.factorize

    i, u = pd.factorize(df.column)
    df.assign(new=len(u) - i)
    
       column  new
    0      10    3
    1      10    3
    2       8    2
    3       8    2
    4       6    1
    5       6    1
    

    dict.setdefault

    d = {}
    for k in df.column:
        d.setdefault(k, len(d))
    
    df.assign(new=len(d) - df.column.map(d))
    

    【讨论】:

      【解决方案2】:

      GroupBy.ngroupascending=False 一起使用:

      df.groupby('column', sort=False).ngroup(ascending=False)+1
      
      0    3
      1    3
      2    2
      3    2
      4    1
      5    1
      dtype: int64
      

      对于看起来像这样的 DataFrame,

      df = pd.DataFrame({'column': [10, 10, 8, 8, 10, 10]})
      

      。 . .如果只对连续值进行分组,您需要修改您的分组器:

      (df.groupby(df['column'].ne(df['column'].shift()).cumsum(), sort=False)
         .ngroup(ascending=False)
         .add(1))
      
      0    3
      1    3
      2    2
      3    2
      4    1
      5    1
      dtype: int64
      

      【讨论】:

      • @anky_91 实际上,从头开始,它似乎根据第一个遇到的值分配因子。
      • 这是pd.factorizenp.unique 之间的巨大差异。 pd.factorize 不会排序,而 np.unique 会。 @anky_91
      • @piRSquared 指出。 :) 对 factorize 有一种直觉,只是不确定。 :)
      • @cs95 我们也可以使用rank。请看我的回答。
      • @BharathM 我投了赞成票(很高兴见到你!)但是我不确定它是否能正常工作。 Rank 将按大小对值进行排名,而不是按出现的顺序(这里的要求)。
      【解决方案3】:

      试试uniquemap

      df.column.map(dict(zip(df.column.unique(),reversed(range(df.column.nunique())))))+1
      Out[350]: 
      0    3
      1    3
      2    2
      3    2
      4    1
      5    1
      Name: column, dtype: int64
      

      【讨论】:

      • 请参阅piR's comment,这将在分配组之前对数据进行排序,这可能不是 OP 想要的(组应按数据存在的顺序分配)。
      • @cs95 我正在尝试解决这个问题,brb
      • 它看起来很老套,但绝对比以前更好。谢谢:)
      • 交换 10 和 8 的位置,你会看到。
      • @piRSquared 很难不使用 np.unique 排序,并且已修复 \
      【解决方案4】:

      实际上,我们可以使用rank,方法为dense,即

      密集:类似于“min”,但组间排名总是增加 1

      df['column'].rank(method='dense')
      
      0    3.0
      1    3.0
      2    2.0
      3    2.0
      4    1.0
      5    1.0
      

      rank 版本的@cs95 的解决方案是

      df['column'].ne(df['column'].shift()).cumsum().rank(method='dense',ascending=False)
      

      【讨论】:

        【解决方案5】:

        IIUC,您希望相同值的连续组的 groupID 以相反的顺序排列。如果是这样,我认为这也应该有效:

        df.column.nunique() - df.column.ne(df.column.shift()).cumsum().sub(1)
        
        Out[691]:
        0    3
        1    3
        2    2
        3    2
        4    1
        5    1
        Name: column, dtype: int32
        

        【讨论】:

          猜你喜欢
          • 2011-01-09
          • 2015-05-02
          • 1970-01-01
          • 2021-11-26
          • 1970-01-01
          • 2011-05-27
          • 2017-07-21
          • 2020-06-07
          • 2015-10-02
          相关资源
          最近更新 更多