我需要使用Pandas编码算法,从第二行开始,从上一行减去列值,并使用结果继续减去下一行,等等。
INPUT:
ID VALUE
0 1
1 10
2 30
3 45
4 78
OUTPUT (just the result, not the operation itself):
ID VALUE
0 1
1 9 #(10-1)
2 21 #(30-9)
3 24 #(45-21)
4 54 #(78-24)
df['VALUE'] = df['VALUE'] - df['VALUE]'.shift() # Doesn't starts with the second row, and use the original dataframe to subtract
df['VALUE'] = df['VALUE'].diff() # Doesn't starts with the second row, and use the original dataframe to subtract
答案 0 :(得分:8)
cumsum
带有交替符号i = np.arange(len(df))
j = np.arange(2)
a = np.where(
(i[:, None] + j) % 2 == 0, 1, -1
) * df.VALUE.values[:, None]
b = a.cumsum(0)[i, i % 2]
df.assign(VALUE=b)
ID VALUE
0 0 1
1 1 9
2 2 21
3 3 24
4 4 54
首先要注意的是
X0 -> X0
X1 -> X1 - X0
X2 -> X2 - X1 + X0
X3 -> X3 - X2 + X1 - X0
X4 -> X4 - X3 + X2 - X1 + X0
所以我想将每隔一行乘以负数...但是对于交替行的另一种选择,我需要这样做两次。
我需要生成一个在两个选项的+和-1之间切换的掩码
i = np.arange(len(df))
j = np.arange(2)
m = np.where(
(i[:, None] + j) % 2 == 0, 1, -1
)
m
array([[ 1, -1],
[-1, 1],
[ 1, -1],
[-1, 1],
[ 1, -1]])
现在我需要在我的df.VALUE
上广播此乘数
a = m * df.VALUE.values[:, None]
a
array([[ 1, -1],
[-10, 10],
[ 30, -30],
[-45, 45],
[ 78, -78]])
注意图案。现在,我cumsum
a.cumsum(0)
array([[ 1, -1],
[ -9, 9],
[ 21, -21],
[-24, 24],
[ 54, -54]])
但是我需要正面的...更具体地说,我需要交替的。因此,我用经过修改的arange
b = a.cumsum(0)[i, i % 2]
b
array([ 1, 9, 21, 24, 54])
这就是我最终分配给现有列的内容
df.assign(VALUE=b)
ID VALUE
0 0 1
1 1 9
2 2 21
3 3 24
4 4 54
这将产生df
的副本,并用VALUE
覆盖b
列。
要坚持这个答案,请确保重新分配一个新名称,或者根据需要重新命名为df
。
df_new = df.assign(VALUE=b)
答案 1 :(得分:3)
很难说是否有熊猫这样做的方法,几个月前我问了这个问题。下面是我的解决方案。
l=[]
for x,y in enumerate(df.VALUE):
if x ==0:
l.append(y)
else :
l.append(y-l[x-1])
l
Out[20]: [1, 9, 21, 24, 54]
答案 2 :(得分:1)
这应该有效:
df = pd.DataFrame({"ID": [0, 1, 2, 3, 4],
"VALUE": [1, 10, 30, 45, 78]})
cumsum_with_parity = df.groupby(df.index % 2).VALUE.cumsum()
df["VALUE"] = cumsum_with_parity - cumsum_with_parity.shift().fillna(0)