R语言 高效压缩多个ifelse语句

2admgd59  于 2023-02-01  发布在  其他
关注(0)|答案(4)|浏览(140)

我有以下几行代码(我在这里重新编码了年龄变量中的特定值),我想用基数R来压缩,最好压缩成一两行。

ibr.sub$Age.recode <- ibr.sub$age
ibr.sub$Age.recode <- ifelse(ibr.sub$age == 4, 3, ibr.sub$Age.recode)
ibr.sub$Age.recode <- ifelse(ibr.sub$age == 20, 18, ibr.sub$Age.recode)
ibr.sub$Age.recode <- ifelse(ibr.sub$age == 22, 24, ibr.sub$Age.recode)
ibr.sub$Age.recode <- ifelse(ibr.sub$age == 26, 24, ibr.sub$Age.recode)
ibr.sub$Age.recode <- ifelse(ibr.sub$age == 31, 30, ibr.sub$Age.recode)
mwyxok5s

mwyxok5s1#

如果测试的数字是唯一可能的x值,则:

y <- 3 * (x == 4) + 18 * (x == 20) + 24 * (x %in% c(22, 26)) + 30 * (x == 31)

或者,如果x也有其他可能的值,则使用上面的值,并遵循以下内容

(y == 0) * x + y
nbewdwxp

nbewdwxp2#

这里的解决方案替换为一个命名向量,您的条目数据可以有更多的值不重新编码,如果必要:
数据:

ibr.sub <- tibble(age = c(4,4,5,6,20,22,23,22,26,31,30,31))

解决方案:

recode_vec = c("4" = "3", "20" = "18", "22" = "24", "26" = "24", "31" = "30")
ibr.sub$Age.recode <- as.numeric(recode_vec[as.character(ibr.sub$age)])

输出:

# A tibble: 12 × 2
     age Age.recode
   <dbl>      <dbl>
 1     4          3
 2     4          3
 3     5         NA
 4     6         NA
 5    20         18
 6    22         24
 7    23         NA
 8    22         24
 9    26         24
10    31         30
11    30         NA
12    31         30

如果您希望将数据保存在Age. recode中,并使用来自年龄的值(不在recode vector中),则需要检查每个值是否产生NA,然后从年龄中获取值:

ibr.sub <- tibble(age = c(4,4,5,6,20,22,23,22,26,31,30,31, 3, 3))
recode_vec = c("4" = "3", "20" = "18", "22" = "24", "26" = "24", "31" = "30")
ibr.sub$Age.recode <- as.numeric(ifelse(is.na(recode_vec[as.character(ibr.sub$age)]), ibr.sub$age, recode_vec[as.character(ibr.sub$age)]))

输出:

# A tibble: 14 × 2
     age Age.recode
   <dbl>      <dbl>
 1     4          3
 2     4          3
 3     5          5
 4     6          6
 5    20         18
 6    22         24
 7    23         23
 8    22         24
 9    26         24
10    31         30
11    30         30
12    31         30
13     3          3
14     3          3
    • 代码说明**:定义recode_vec,它只是一个命名向量(向量中的每个元素都有一个关联的名称,equal的左侧是名称,右侧是值):
> recode_vec
   4   20   22   26   31 
 "3" "18" "24" "24" "30"

这样,您就像一个字典。ibr.sub$age是数字,因此您可以转换为字符来处理recode_vecas.character(ibr.sub$age))。
现在,要访问一个命名向量中的元素,你只需要把元素的名称放在括号中。

> recode_vec["4"]
  4 
"3" 
> recode_vec["5"] # "5" don´t exist in vector, so return NA
<NA> 
  NA

如果你传递一个带有名称的向量(在这里名称是ibr.sub$age中的值,就像字符一样),那么就转换这个向量:

> recode_vec[c("4", "4", "5")]
   4    4 <NA> 
 "3"  "3"   NA

最后,检查ifelse子句值的转换,如NA(直接使用返回逻辑值的is.na),用列age中的原始数据替换这些大小写。所有这些都将生成一个字符向量,因此可以选择使用as.numeric转换为数字。

8cdiaqws

8cdiaqws3#

像这样?

current <- c(4, 20, 22, 26, 31)
new <- c(3, 18, 24, 24, 30)

i <- match(ibr.sub$age, current)
ibr.sub$Age.recode <- ibr.sub$age
ibr.sub$Age.recode[i] <- new[i]

仅在三个指令中:

i <- match(ibr.sub$age, c(4, 20, 22, 26, 31))
ibr.sub$Age.recode <- ibr.sub$age
ibr.sub$Age.recode[i] <- c(3, 18, 24, 24, 30)[i]

如果列age的值不在向量c(4, 20, 22, 26, 31)中,则match指令将包含NA,索引将出错。

i <- match(ibr.sub$age, c(4, 20, 22, 26, 31))
ok <- !is.na(i)
ibr.sub$Age.recode <- ibr.sub$age
ibr.sub$Age.recode[ i[ok] ] <- c(3, 18, 24, 24, 30)[ i[ok] ]
62lalag4

62lalag44#

最好的方法是使用tidyverse

ibr.sub %>%                 # your data.frame
 rename(age= Age) %>%       # rename col from Age to age
 mutate( age = case_when(   # case_when : what to change in each case
    age == 4 ~ 3,           # when age == 4, change to 3
    age == 20 ~ 18,         # same thing
    age == 22 ~ 24,
    age == 26 ~ 24,
    age == 31 ~ 30,
    TRUE ~ age) )           # if the value is already TRUE, keep it.

它将返回此 Dataframe (不包含col Age,我添加该列只是为了说明):

id Age age
1  1   3   3
2  2   4   3
3  3   5   5
4  4  20  18
5  5  21  21
6  6  22  24
7  7  26  24
8  8  31  30

相关问题