如果另一个变量等于 R 中的设定值,如何使用来自不同变量的值创建新变量?
How to create a new variable with values from different variables if another variable equals a set value in R?
我有一个复杂的问题,我将尝试通过简化我的数据集来简化它。假设我有 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
这在 Date=NA 的新变量中正确地留下了 NA,但是提供的值不是来自 va、vb 或 vc,而是完全来自其他一些值。如果日期为 'a',如何使 df$new 等于 va,如果日期为 'b',则为 vb,如果日期为 'c',如何使 df$new 等于 va ?
有人告诉我我的代码的问题是我需要在两边放置索引。没有右侧的索引,它不知道从哪一行应用值。所以在这种情况下正确的代码是:
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
当我在 link 处添加到他的回答时,我发现更好的方法是将 == 替换为 %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)]
尝试
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)
您也可以使用 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
我有一个复杂的问题,我将尝试通过简化我的数据集来简化它。假设我有 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
这在 Date=NA 的新变量中正确地留下了 NA,但是提供的值不是来自 va、vb 或 vc,而是完全来自其他一些值。如果日期为 'a',如何使 df$new 等于 va,如果日期为 'b',则为 vb,如果日期为 'c',如何使 df$new 等于 va ?
有人告诉我我的代码的问题是我需要在两边放置索引。没有右侧的索引,它不知道从哪一行应用值。所以在这种情况下正确的代码是:
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
当我在 link 处添加到他的回答时,我发现更好的方法是将 == 替换为 %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)]
尝试
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)
您也可以使用 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