R 中基于列值的行之间的差异

Difference between rows in R based on column values

我是 R 的新手,正在学习基础知识。我在 R 中有一个数据框,其中包含 controller_id、user_id、mth_id、col_val1 到 col_val100 等列。

df <- data.frame('controller_id' = c('X','X','X','X','X','X','Y','Y','Y','Y','Y','Y','Z','Z'),
'user_id'=c('A','B','C','A','B','C','P','Q','R','P','Q','R',NA,NA),
'mth_id'=c('1393','1393','1393','1398','1398','1398','1393','1393','1393','1398','1398','1398','1393','1398'),
'col_val1' = c(5,4,6,3,1,10,12,15,18,13,19,1,5,2),
'col_val2'=c(8,12,9,2,12,5,7,9,11,4,0,7,10,5))

> df
   controller_id user_id mth_id col_val1 col_val2
1              X       A   1393        5        8
2              X       B   1393        4       12
3              X       C   1393        6        9
4              X       A   1398        3        2
5              X       B   1398        1       12
6              X       C   1398       10        5
7              Y       P   1393       12        7
8              Y       Q   1393       15        9
9              Y       R   1393       18       11
10             Y       P   1398       13        4
11             Y       Q   1398       19        0
12             Y       R   1398        1        7
13             Z    <NA>   1393        5       10
14             Z    <NA>   1398        2        5

我想要的是根据特定的 user_id、mth_id 计算每个 controller_id 的 col_values 的差异,并仅显示那些 col_values随着 mth_id 的增加而减少。

例如:对于 controller_id = X,对于两个不同的 mth_id,我们有 3 个 user_id 作为 A、B、C。代码应该计算 mth_id 1398 的 col_val1 和所有 3 users_id 的 1393 之间的差异,如果该差异 < 0 那么我想要一个像

这样的输出
Col_val1 for controller_id 'X', user_id 'A' has decreased from 5 to 3

如果对于给定的 controller_id 没有关联的 user_id 那么它应该计算 controller_id 本身之间的列值差异。

理想情况下,我想将这些输出存储在 list/dataframe 中供以后使用。 此外,代码是 运行 大约。数据框中存在 900 列。

我正在将除 controller_id、User_id、mth_id 之外的所有列转换为数字字段,然后计算每个 user_id 的结果(采用单个列)使用'data.table'

> df[,4:ncol(df)] <- sapply(df[,4:ncol(df)],as.numeric)
> result_col1 <- setDT(df)[,val_diff := col_val1 - lag(col_val1,1L), by=user_id]

> result_col1
    controller_id user_id mth_id col_val1 col_val2 val_diff
  1:             X       A   1393        5        8       NA
  2:             X       B   1393        4       12       NA
  3:             X       C   1393        6        9       NA
  4:             X       A   1398        3        2       -2
  5:             X       B   1398        1       12       -3
  6:             X       C   1398       10        5        4
  7:             Y       P   1393       12        7       NA
  8:             Y       Q   1393       15        9       NA
  9:             Y       R   1393       18       11       NA
 10:             Y       P   1398       13        4        1
 11:             Y       Q   1398       19        0        4
 12:             Y       R   1398        1        7      -17
 13:             Z      NA   1393        5       10       NA
 14:             Z      NA   1398        2        5       -3

但是,我想在 Controller_id 级别实现类似的事情。我知道这样的工作流程 - 选择一个控制器 ID - 查看我们是否有 user_id 。如果我们有,那么我们比较 1393 和 1398 的 user_id 列值并查看差异。但不知何故,我无法对此进行编码。

如有任何帮助,我们将不胜感激。

白底 R:

usplit<-with(df,split(df,controller_id))

rsl<-lapply(usplit,function(dt){
  do.call("rbind",by(dt,factor(dt[,"user_id"],exclude = NULL),function(vt){
    n1=1:nrow(vt)
    cbind(vt,rbind(NA,vt[n1[-1],4:5]-vt[n1[-length(n1)],4:5]))
  }))
})

do.call("rbind",rsl)

> do.call("rbind",rsl)
        controller_id user_id mth_id col_val1 col_val2 col_val1 col_val2
X.A.1               X       A   1393        5        8       NA       NA
X.A.4               X       A   1398        3        2       -2       -6
X.B.2               X       B   1393        4       12       NA       NA
X.B.5               X       B   1398        1       12       -3        0
X.C.3               X       C   1393        6        9       NA       NA
X.C.6               X       C   1398       10        5        4       -4
Y.P.7               Y       P   1393       12        7       NA       NA
Y.P.10              Y       P   1398       13        4        1       -3
Y.Q.8               Y       Q   1393       15        9       NA       NA
Y.Q.11              Y       Q   1398       19        0        4       -9
Y.R.9               Y       R   1393       18       11       NA       NA
Y.R.12              Y       R   1398        1        7      -17       -4
Z.NA.13             Z    <NA>   1393        5       10       NA       NA
Z.NA.14             Z    <NA>   1398        2        5       -3       -5

如果那是你想要的,最后两列是差异,因为最终结果是 data.frame 很容易改变。