在 R 中有条件地更改变量中的值

Changing values in variables conditionally in R

    Romance     Horror Comedy  Keyword    
       0          1      1       lol         
       1          0      0       love         
       0          0      1       lol          
       1          1      0       omg           
 

大家好,我有一个像上面这样的数据集,我会用R来工作。我想要的是这样的:

如果keyword="lol",则喜剧=1,其他=0

如果关键字=“omg”,则恐怖=1,其他=0

If keyword= "love", make Romance=1, others=0

实际上,我试过 ifelse 语句,但没有用。顺便提一下,我有大约 200 个案例和 6 个变量。暂时谢谢了。

将前三列的列值更改为 1

df1[1:3] <- 0

然后,创建一个命名向量以匹配列名

nm1 <- setNames(c("Comedy", "Romance", "Horror"), c("lol", "love", "omg"))

根据'Keyword'的替换值,使用向量match'df1'的列名得到列索引,cbind用行索引,使用 row/column 索引的矩阵将数据集中的那些元素分配给 1

df1[1:3][cbind(seq_len(nrow(df1)), match(nm1[df1$Keyword], names(df1)))] <- 1

数据

df1 <- structure(list(Romance = c(0L, 1L, 0L, 1L), Horror = c(1L, 0L, 
0L, 1L), Comedy = c(1L, 0L, 1L, 0L), Keyword = c("lol", "love", 
"lol", "omg")), class = "data.frame", row.names = c(NA, -4L))

这是虚拟或一次性编码,因此您可以将 model.matrix 与因子(或字符)向量和没有截距的公式一起使用:

~ x + 0
~ x - 1

两者都可以。

dat <- read.table(header = TRUE, text = "Romance     Horror Comedy  Keyword
0          1      1       lol
1          0      0       love
0          0      1       lol
1          1      0       omg")

key <- c(Romance = 'love', Horror = 'omg', Comedy = 'lol')

tmp <- factor(dat$Keyword, key, names(key))

data.frame(model.matrix(~ tmp + 0))
#   tmpRomance tmpHorror tmpComedy
# 1          0         0         1
# 2          1         0         0
# 3          0         0         1
# 4          0         1         0

由于 key(因此因子的水平)与您的列具有相同的顺序,您也可以直接替换列:

dat[, 1:3] <- model.matrix(~ tmp + 0)
dat
#   Romance Horror Comedy Keyword
# 1       0      0      1     lol
# 2       1      0      0    love
# 3       0      0      1     lol
# 4       0      1      0     omg

编辑

要将多个单词映射到一个类型,您可以使用一个列表作为您的键:

keywords <- c('lol', 'freak', 'kiss', 'ring', 'unknown', 'omg')

key <- list(
  Romance = c('love', "kiss", "ring"),
  Horror = c('omg', "freak", "kill"),
  Comedy = 'lol'
)

lst <- stack(key)
tmp <- lst$ind[match(keywords, lst$values)]

data.frame(model.matrix(~ tmp + 0))
#   tmpRomance tmpHorror tmpComedy
# 1          0         0         1
# 2          0         1         0
# 3          1         0         0
# 4          1         0         0
# 6          0         1         0

请注意,以上内容与列表中缺少的关键字不匹配(缺少第 5 行),因此为这些设置一个单独的类别也会很有用:

key <- c(key, Other = setdiff(keywords, unlist(key)))

lst <- stack(key)
tmp <- lst$ind[match(keywords, lst$values)]

data.frame(model.matrix(~ tmp + 0), keywords)
#   tmpRomance tmpHorror tmpComedy tmpOther keywords
# 1          0         0         1        0      lol
# 2          0         1         0        0    freak
# 3          1         0         0        0     kiss
# 4          1         0         0        0     ring
# 5          0         0         0        1  unknown
# 6          0         1         0        0      omg

现在第 5 行显示正确


edit2

我刚刚了解到 R >= 3.5.0 最终 允许重复的标签,所以而不是做

key <- c(key, Other = setdiff(keywords, unlist(key)))
lst <- stack(key)
lst$ind[match(keywords, lst$values)]
# [1] Comedy  Horror  Romance Romance Other   Horror 
# Levels: Romance Horror Comedy Other

你可以简单地做

factor(keywords, unlist(key), rep(names(key), lengths(key)))
# [1] Comedy  Horror  Romance Romance Other   Horror 
# Levels: Romance Horror Comedy Other