如何逐渐减少pandas数据框中一列的值

3

Suppose I have a dataframe as listed below:

[1] df
    name   value
     a      116
     b      116
     c      116
     d      225
     e      225
     f      225
     g      225

现在我希望将df变成:
    name   value
     a      116
     b      115
     c      114
     d      225
     e      224
     f      223
     g      222

也就是说,无论原始数据框在连续的行中某一列具有相同(固定)值的位置,它都应该逐渐减少1。因此,名称为a、b、c的值列中的值从116降到114。d、e、f、g的值从225降到222。

请指教。


1
如果它们的值相同但不连续呢?比如,如果还有一行'h',其值为'116',会怎样? - rafaelc
6个回答

5

使用GroupBy.cumcount来计算连续值,并从value列中减去:

#consecutive rows to Series g
g = df['value'].ne(df['value'].shift()).cumsum()
df['value'] = df['value'] - df.groupby(g).cumcount()
print (df)
  name  value
0    a    116
1    b    115
2    c    114
3    d    225
4    e    224
5    f    223
6    g    222

3
总是没有理由,我真的厌倦了毫无理由地被踩票 :-( - BENY

3
如果连续的数值是唯一的,您可以使用 transform
df.groupby('value').value.transform(lambda k: k - k.reset_index().index)

0    116
1    115
2    114
3    225
4    224
5    223
6    222

如果您有非连续的相同值块(如您的评论中,最后的116也会被减去),则此方法将无效。除非这就是 OP 想要的,这是可能的(有点不清楚)... - sacuL

3

使用cumcount

df.value-=df.groupby('value').cumcount()
df
Out[215]: 
  name  value
0    a    116
1    b    115
2    c    114
3    d    225
4    e    224
5    f    223
6    g    222

2

也许有更简洁的方法,但你可以像这样获得所需的结果:

df['value'] = (df.assign(x = df.value.diff().ne(0).cumsum())
               .groupby('x')
               .value
               .transform(lambda y: y - y.reset_index().index))
>>> df
  name  value
0    a    116
1    b    115
2    c    114
3    d    225
4    e    224
5    f    223
6    g    222

本质上,这创建了一个列,用于标识连续的相等数字块(我称之为x),对该列进行分组,然后减去reset_index的结果,它只是一个range对象,每个连续组的长度(即从第一组减去0,从第二组减去1,以此类推...)


0
def function1(dd:pd.DataFrame):
    dd1=dd.assign(col2=1)
    return dd.assign(value=dd1.col2.cumsum().mul(-1).add(1).add(dd1['value']))

col1=df1['value'].diff().ne(0).cumsum()
df1.groupby(col1).apply(function1)

输出:

 name  value
0    a    116
1    b    115
2    c    114
3    d    225
4    e    224
5    f    223
6    g    222

0

我认为首先你需要对数据框的值列进行排序,然后就可以使用一个简单的for循环来处理递减的值。

dataframe = dataframe.sort_values('value')                  #sort column 'value' 
j=0
for i in range(len(dataframe.index)-1):
    if(dataframe.iloc[i, 1] == dataframe.iloc[i+1,1]):            #if ith row value is equal to i+1th row value
        dataframe.iloc[i,1] = dataframe.iloc[i,1] - j             #then decrease 
        j = j + 1

    elif(dataframe.iloc[i, 1] != dataframe.iloc[i+1,1]):          # if not then decrease ith row value and again start with
        dataframe.iloc[i,1] = dataframe.iloc[i,1] - j             # j=0
        j=0

#print(j)                                                          
#print(i)
if(dataframe.iloc[i+1,1] == dataframe.iloc[i-j+1,1]):           # for last row check whether it is repeatation of original value
    dataframe.iloc[i+1,1] = dataframe.iloc[i+1,1] - j           # or not, if it is then decrease it.               

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