【问题标题】:How to create a new variable with values from different variables if another variable equals a set value in R?如果另一个变量等于 R 中的设定值,如何使用来自不同变量的值创建一个新变量?
【发布时间】:2015-05-07 23:24:56
【问题描述】:

我有一个复杂的问题,我将尝试通过简化我的数据集来简化它。假设我有 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,而是完全来自其他一些值。如果日期为“a”,如何使 df$new 等于 va,如果日期为“b”,则为 vb,如果日期为“c”,则为 vc?

【问题讨论】:

  • 请通过 (1) 输入 a,b,c 的值 (2) 不使用 ... 等使其可重现。我们无法按原样复制粘贴您的代码来制作示例。考虑使用dput(head(df)) 并在此处查看:stackoverflow.com/questions/5963269/…
  • 列和日期是否实际命名为 va、vb、vc、a、b、c?这比实际上不匹配的名称更容易。
  • @Molx:列的名称是 FSLE20060813、FSLE20060814 等,而日期的名称是 2006-08-13、2006-08-14 等。
  • @Frank:我输入的值不是我的实际值,因为数据集在两个维度上都比我提供的要大得多。我不知道生成随机数的代码,所以我不想添加需要修复的另一行。出于可重现的目的,您可以使用随机数生成器,或执行类似 df$va

标签: r conditional conditional-statements subset


【解决方案1】:

试试

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)

【讨论】:

    【解决方案2】:

    您也可以使用base R 进行row/column 索引(使用来自@ExperimenteR 的数据)。即使有 100 个 unique 'Date' 和对应的 'v' 列,我们也可能不需要更改代码,尤其是 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
    

    【讨论】:

      【解决方案3】:

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

      df$new[df$date=='a' & !is.na(df$date)] <- df$va[df$date=='a' & !is.na(df$date)]
      df$new[df$date=='b' & !is.na(df$date)] <- df$vb[df$date=='b' & !is.na(df$date)]
      df$new[df$date=='c' & !is.na(df$date)] <- df$vc[df$date=='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

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

      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)]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-07-23
        • 2022-01-03
        • 2019-03-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多