如何计算特定于每条线上提供的ID的值?

Tom*_*Tom 0 python r pandas

我有一个值如下所示的数据表:

Score ID
1.2    1
2.4    1
1.1    1
1.9    1
2.4    2
3.5    2
2.2    2
1.1    3
1.1    3
1.7    3
3.1    3
2.2    3
Run Code Online (Sandbox Code Playgroud)

我真正需要的是在单独的列中计算每个ID的更改分数,使其看起来像这样:

Score   ID  Changes
1.2     1   
2.4     1   1.2
1.1     1   -1.3
1.9     1   0.8
2.4     2   
3.5     2   1.1
2.2     2   -1.3
1.1     3   
1.1     3   0
1.7     3   0.6
3.1     3   1.4
2.2     3   -0.9
Run Code Online (Sandbox Code Playgroud)

注意每个"变化"是如何通过取得前一个分数并从当前分数中减去来计算的:例如,在第一个变化中,你得到1.2乘1.2 = 2.4(当前分数) - 1.2(前一个分数)

问题是这些分数只能仅与ID范围内的分数有关.你不能只是迭代并取得分数的差异.我该怎么做?我可以使用什么逻辑来测试在同一ID中包含"更改"?我熟悉R或python(或BASH)来做到这一点.

luk*_*keA 5

在R可能:

transform(
  df, 
  Changes = ave(df$Score, df$ID, FUN = function(x) c(NA, diff(x)))
)
#    Score ID Changes
# 1    1.2  1      NA
# 2    2.4  1     1.2
# 3    1.1  1    -1.3
# 4    1.9  1     0.8
# 5    2.4  2      NA
# 6    3.5  2     1.1
# 7    2.2  2    -1.3
# 8    1.1  3      NA
# 9    1.1  3     0.0
# 10   1.7  3     0.6
# 11   3.1  3     1.4
# 12   2.2  3    -0.9
Run Code Online (Sandbox Code Playgroud)

df 保存您的原始数据框.


关于@Bulat的评论:

id<- c(1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3)
score <-  c(1.2, 2.4, 1.1, 1.9, 2.4, 3.5, 2.2, 1.1, 1.1, 1.7, 3.1, 2.2)
library(data.table)
df <- data.frame(id, score)
dt = data.table(id, score)
library(microbenchmark)
microbenchmark(
  dt = dt[ , diff := c(NA, diff(score)), by = id],
  df = df$diff <- ave(df$score, df$id, FUN = function(x) c(NA, diff(x))),
  times = 1000
)
# Unit: microseconds
#  expr      min        lq      mean    median        uq      max neval cld
#    dt 1121.931 1225.2660 1342.4626 1269.5530 1321.2210 5908.411  1000   b
#    df  397.175  488.2085  547.8198  525.8175  586.7995 7784.270  1000  a 
Run Code Online (Sandbox Code Playgroud)