数据框中的条件计算

use*_*194 6 r dplyr

我经常需要根据因子变量的条件从数据框中的现有变量计算新变量.

编辑在2分钟内获得4个答案,我意识到我已经过度简化了我的例子.请看下面.

简单的例子:

df <- data.frame(value=c(1:5),class=letters[1:5])
df
value class
1     a
2     b
3     c
4     d
5     e
Run Code Online (Sandbox Code Playgroud)

我可以使用这样的代码

df %>% 
    mutate(result=NA) %>%
    mutate(result=ifelse(class=="a",value*1,result)) %>%
    mutate(result=ifelse(class=="b",value*2,result)) %>%
    mutate(result=ifelse(class=="c",value*3,result)) %>%
    mutate(result=ifelse(class=="d",value*4,result)) %>%
    mutate(result=ifelse(class=="e",value*5,result))
Run Code Online (Sandbox Code Playgroud)

对我的变量执行条件计算,得到

value class result
 1     a      1
 2     b      4
 3     c      9
 4     d     16
 5     e     25
Run Code Online (Sandbox Code Playgroud)

实际上,类的数量更大,计算更复杂,但是,我更喜欢更清洁的东西,就像这样

df %>%
mutate(results=switch(levels(class),
                    "a"=value*1,
                    "b"=value*2,
                    "c"=value*3,
                    "d"=value*4,
                    "e"=value*5))
Run Code Online (Sandbox Code Playgroud)

这显然不起作用

Error in switch(levels(1:5), a = 1:5 * 1, b = 1:5 * 2, c = 1:5 * 3, d =  1:5 *  : 
  EXPR must be a length 1 vector
Run Code Online (Sandbox Code Playgroud)

有没有办法用dplyr管道(或其他)更好地做到这一点?

编辑 实际上,我有更多的值变量要包含在我的计算中,它们不是简单的连续向量,它们是数千行测量数据.

这是我的第二个随机值变量的简单示例(同样,它在我的实际数据中更多)

df <- data.frame(value1=c(1:5),value2=c(2.3,3.6,7.2,5.6,0),class=letters[1:5])
value1 value2 class
  1    2.3     a
  2    3.6     b
  3    7.2     c
  4    5.6     d
  5    0.0     e
Run Code Online (Sandbox Code Playgroud)

我的计算对每种情况都不同.我明白我可以这样简化一下

df %>% 
mutate(result=NA,
     result=ifelse(class=="a",value1*1,result),
     result=ifelse(class=="b",value1/value2*4,result),
     result=ifelse(class=="c",value2*3.57,result),
     result=ifelse(class=="d",value1+value2*2,result),
     result=ifelse(class=="e",value2/value1/5,result))
Run Code Online (Sandbox Code Playgroud)

但是,类似于上述开关示例的工作解决方案甚至更清洁.

ags*_*udy 9

不需要在ifelse这里使用,你可以使用merge:

df <- data.frame(value=c(1:5),class=letters[1:5])
cond <- data.frame(ratio=c(1:5),class=letters[1:5])
transform(merge(df,cond),result=value*ratio)

  class value ratio result
1     a     1     1      1
2     b     2     2      4
3     c     3     3      9
4     d     4     4     16
5     e     5     5     25
Run Code Online (Sandbox Code Playgroud)

OP编辑后

看起来OP想要为每个类应用不同的函数.这是一个data.table解决方案.我认为它简单易读.首先,我为每个因素创建函数:

## here each function takes a data.table as an single argument
fns <- list(
  function(x) x[,value1]*1,
  function(x) x[,value1]/x[,value2]*4,
  function(x) x[,value2]*3.57,
  function(x) x[,value1]+x[,value2]*2,
  function(x) x[,value2]/x[,value1]/5
)
## create a names list here 
## the names here are just the class factors
fns <- setNames(fns,letters[1:5])
Run Code Online (Sandbox Code Playgroud)

按类应用函数很简单.我创建了函数名,我用do.call它来命名函数

## using data.table here for grouping feature
## .SD is the rest of columns except the grouping variable
## the code can also be written in dplyr or in base-R
library(data.table)
setDT(df)[,value:= fns[[class]](.SD),by=class]

     value1 value2 class     value
 1:      1    2.3     a  1.000000
 2:      2    3.6     b  2.222222
 3:      3    7.2     c 25.704000
 4:      4    5.6     d 15.200000
 5:      5    0.0     e  0.000000
 6:      1    2.3     a  1.000000
 7:      2    3.6     b  2.222222
 8:      3    7.2     c 25.704000
 9:      4    5.6     d 15.200000
10:      5    0.0     e  0.000000
Run Code Online (Sandbox Code Playgroud)

我用这个df:

df <- data.frame(value1=c(1:5),value2=c(2.3,3.6,7.2,5.6,0),
                 class=rep(letters[1:5],2))
Run Code Online (Sandbox Code Playgroud)