如果另一个变量等于R中的设定值,如何用不同变量的值创建一个新变量?

时间:2015-05-07 23:24:57

标签: r conditional conditional-statements subset

我有一个复杂的问题,我将通过简化数据集来尝试简化。假设我有5个变量:

df$Id <- c(1:12)
df$Date <- c(NA,NA,a,a,b,NA,NA,b,c,c,b,a)
df$va <- c(1.1, 1.4, 2.5, ...)     #12 randoms values
df$vb <- c(5.9, 2.3, 4.7, ...)     #12 other random values
df$vc <- c(3.0, 3.3, 3.7, ...)     #12 more random values

然后我想创建一个新变量,如果日期等于a,b或c,则从va,vb或vc获取值。我曾尝试过嵌套的if-else,但是没有用。我也尝试过:

df$new[df$date=='a' & !is.na(df$date)] <- df$va
df$new[df$date=='b' & !is.na(df$date)] <- df$vb
df$new[df$date=='c' & !is.na(df$date)] <- df$vc

这正确地将NA保留在新变量中,其中Date = NA,但是提供的值不是来自va,vb或vc,而是来自其他一些值。如果日期是&#39; a&#39;如果日期是&#39; b&#39;如果日期是&#39; c&#39,我如何得到df $ new等于va ;

3 个答案:

答案 0 :(得分:5)

尝试

library(dplyr)
df %>% 
    mutate(new = (Date=="a")*va + (Date=="b")*vb + (Date=="c")*vc)
#   Id Date         va        vb         vc       new
#1   1 <NA> 0.26550866 0.6870228 0.26722067        NA
#2   2 <NA> 0.37212390 0.3841037 0.38611409        NA
#3   3    a 0.57285336 0.7698414 0.01339033 0.5728534
#4   4    a 0.90820779 0.4976992 0.38238796 0.9082078
#5   5    b 0.20168193 0.7176185 0.86969085 0.7176185
#6   6 <NA> 0.89838968 0.9919061 0.34034900        NA
#7   7 <NA> 0.94467527 0.3800352 0.48208012        NA
#8   8    b 0.66079779 0.7774452 0.59956583 0.7774452
#9   9    c 0.62911404 0.9347052 0.49354131 0.4935413
#10 10    c 0.06178627 0.2121425 0.18621760 0.1862176
#11 11    b 0.20597457 0.6516738 0.82737332 0.6516738
#12 12    a 0.17655675 0.1255551 0.66846674 0.1765568

或者,

library(data.table)
setDT(df)[,new:= (Date=="a")*va + (Date=="b")*vb + (Date=="c")*vc,]

数据

set.seed(1)
df <- data.frame(Id = 1:12,
                 Date = c(NA,NA,"a","a","b",NA,NA,"b","c","c","b","a"),
                 va = runif(12),
                 vb = runif(12),
                 vc = runif(12), stringsAsFactors = FALSE)

答案 1 :(得分:1)

您也可以使用row/column进行base R索引(使用@ExperimenteR中的数据)。即使有unique&#39;日期&#39;与相应的&#39; v&#39;列,我们可能不需要更改代码,尤其是cbind(..)部分。

  df$new <- df[-(1:2)][cbind(1:nrow(df),match(df$Date, sort(unique(df$Date))))]
  df
  #   Id Date         va        vb         vc       new
  #1   1 <NA> 0.26550866 0.6870228 0.26722067        NA
  #2   2 <NA> 0.37212390 0.3841037 0.38611409        NA
  #3   3    a 0.57285336 0.7698414 0.01339033 0.5728534
  #4   4    a 0.90820779 0.4976992 0.38238796 0.9082078
  #5   5    b 0.20168193 0.7176185 0.86969085 0.7176185
  #6   6 <NA> 0.89838968 0.9919061 0.34034900        NA
  #7   7 <NA> 0.94467527 0.3800352 0.48208012        NA
  #8   8    b 0.66079779 0.7774452 0.59956583 0.7774452
  #9   9    c 0.62911404 0.9347052 0.49354131 0.4935413
  #10 10    c 0.06178627 0.2121425 0.18621760 0.1862176
  #11 11    b 0.20597457 0.6516738 0.82737332 0.6516738
  #12 12    a 0.17655675 0.1255551 0.66846674 0.1765568

答案 2 :(得分:0)

我被告知我的代码问题是我需要在任何一方放置索引。如果没有右侧的索引,则不知道应用该值的行。所以在这种情况下正确的代码是:

df$new[df$date %in% 'a' & !is.na(df$date)] <- df$va[df$date %in% 'a' & !is.na(df$date)]
df$new[df$date %in% 'b' & !is.na(df$date)] <- df$vb[df$date %in% 'b' & !is.na(df$date)]
df$new[df$date %in% 'c' & !is.na(df$date)] <- df$vc[df$date %in% 'c' & !is.na(df$date)]

或者,另一位用户注意到有一种方法可以使用ifelse,这可以在这里被视为正确的答案:https://stats.stackexchange.com/questions/151345/how-to-create-a-new-variable-with-values-from-different-variables-if-another-var

当我在该链接中添加回答时,我发现更好的方法是将%替换为%=%,以便创建一个数字变量而不是一个列表,其中包含36121个观察值的每一个我的数据集(我提供的示例中有12个)。那看起来像是:

$_POST