如何从熊猫数据框的列中逐步减少值

时间:2018-07-09 13:27:07

标签: python pandas

假设我有一个如下所示的数据框:

[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

也就是说,无论原始df在连续行的列中具有相同(固定)值的位置,都应逐渐减小1。因此,名称a,b,c的value列中的值将从116变为114。 d,e,f,g从225升至222。

请指教。

5 个答案:

答案 0 :(得分: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

答案 1 :(得分: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

答案 2 :(得分: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

答案 3 :(得分: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的结果,该结果只是一个{{ 1}}对象,即每个连续组的长度(即从第一组减去range,从第二组减去0,依此类推...)

答案 4 :(得分:0)

我认为首先您必须对dataframe值列进行排序,然后才可以使用简单的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.