R中行的差异基于列值

时间:2016-07-21 00:10:15

标签: r dataframe apply

我是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的差异,并仅显示随着mth_id的增加而减少的col_values。

例如:对于controller_id = X,我们有3个user_id作为A,B,C用于两个不同的mth_id。代码应该为所有3个users_id计算m__id 1398和1393的col_val1之间的差异,并且如果该差异是&lt; 0然后我想要像

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

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

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

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

> 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列值并查看差异。但不知何故,我无法对此进行编码。

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

Whit base 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很容易改变。