使用Pandas按降序列举分组信息

4

我有以下列:

   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


那我会将列表平铺并按降序排序。还有其他更简单的解决方案吗?
谢谢。
5个回答

6

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))

5
请使用GroupBy.ngroup,并加上参数ascending=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

1
@anky_91 其实,刚才说错了,看起来它是根据第一个遇到的值来分配因子。 - cs95
2
pd.factorizenp.unique之间存在巨大的区别。pd.factorize不排序,而np.unique则会进行排序。@anky_91 - piRSquared
@piRSquared 注意到了。 :) 对于因式分解有一种直觉,只是不太确定。 :) - anky
@cs95 我们也可以使用 rank。请看我的答案。 - Bharath M Shetty
@BharathM 我已经点赞了(很高兴见到你!),但是我不确定它是否适用于一般情况。Rank将通过大小对值进行排名,而不是按出现顺序排列(这是此处的要求)。 - cs95
@cs95,我完全误解了,现在我看到了答案的第二部分。 :) - Bharath M Shetty

3
实际上,我们可以使用 rank 函数,并选择 dense 方法。简而言之,这意味着在分组之间,排名总是增加1。
df['column'].rank(method='dense')

0    3.0
1    3.0
2    2.0
3    2.0
4    1.0
5    1.0
< p >@cs95的解决方案的rank版本如下:

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

2

Try with unique and map

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的评论,在分配组之前对数据进行排序可能不是OP想要的(应按照数据出现的顺序分配组)。 - cs95
@cs95 我正在尝试修复,马上回来。 - BENY
这看起来有点巧妙,但肯定比以前好。谢谢 :) - cs95
交换10和8的位置,你就会看到。 - piRSquared
@piRSquared,如果不使用np.unique排序并修复,那就很难了。 - BENY

1

如果我理解正确,您希望以相同值连续组的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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接