使用包含NA或由空格分隔的整数系列的因子变量,我试图创建一系列虚拟变量(var1,var2,...,vari),如果字符串包含整数,则取值为1 i(不仅仅是字符i),如果字符串包含NA则为NA,否则为0。
我有些卡住,因为我尝试使用grep()在字符串中搜索定义每个整数的字符,但这会返回行号而不是boole矢量。此外,搜索" 7"返回" 77"," 97"等等而不仅仅是#34; 7"。
因此,在下面的最小工作数据中,我希望虚拟变量var0,var1,var2,var3,var33,var999,如果data == NA则取NA值,如果data == x则取1,否则取0。我已经放下了最初的尝试来解决这个问题。由于我的实际数据非常大,我正在寻找一种通用的方法。
# Create data
data <- c("0 1 2", "0 2 3", "999", "33", "33 0 3", NA, "33 0 3") %>% factor()
# Attempt to complete task (doesn't work)
data <- cbind(data,
setNames(
data.frame(
sapply(
data,
function(i) ifelse(is.na(data),
NA,
ifelse(# do something to create variables w/ value 1,0)))),
paste0("var",
valuenumber))
在这种情况下,所需的输出类似于:
data$var0
[1] 1, 1, 0, 0, 1, NA, 1 # = 1 when string contains "0", NA when NA, 0 o/w
data$var1
[1] 1, 0, 0, 0, 0, NA, 0 # = 1 when string contains "1", NA when NA, 0 o/w
data$var2
[1] 1, 1, 0, 0, 0, NA, 0 # = 1 when string contains 2, NA when NA, 0 o/w
# Important note: I want below to indicate when the string contains "3" and NOT "33"
data$var3
[1] 0, 1, 0, 0, 1, NA, 1 # = 1 when string contains 3, NA when NA, 0 o/w.
# Important note: I want below to indicate when the string contains "33" and NOT "3"
data$var33
[1] 0, 0, 0, 1, 1, NA, 1
data$var999
[1] 0, 0, 1, 0, 0, NA, 0
答案 0 :(得分:2)
您需要使用grepl
返回T
或F
而不是grep
,它会返回匹配的值或匹配的位置,并且因为您正在使用字符串从字符开始而不是从因素开始更好,这里有一些关于如何做的开始。将变量名重命名为Vari
应该提供所需的输出:
data <- c("0 1 2", "0 2 3", "999", "33", "33 0 3", NA, "33 0 3")
valueNumbers <- na.omit(unique(unlist(strsplit(data, " "))))
newData <- sapply(valueNumbers, function(i) replace(as.integer(
grepl(paste("\\b", i, "\\b", sep = ""), data)), is.na(data), NA))
newData
0 1 2 3 999 33
[1,] 1 1 1 0 0 0
[2,] 1 0 1 1 0 0
[3,] 0 0 0 0 1 0
[4,] 0 0 0 0 0 1
[5,] 1 0 0 1 0 1
[6,] NA NA NA NA NA NA
[7,] 1 0 0 1 0 1
为了处理评论中提及的3
和33
个案例,您可以在grepl中的模式中添加单词边界\\b
,这将区分3
和33
。
答案 1 :(得分:1)
使用strsplit并匹配:
# data
data <- factor(c("0 1 2", "0 2 3", "999", "33", "33 0 3", NA, "33 0 3"))
# make list
dList <- sapply(as.character(data), strsplit, split = " ")
# unique items
items <- sort(unique(unlist(dList)))
# result
res <- data.frame(!is.na(t(sapply(dList, match, x = items)))) * 1
colnames(res) <- paste0("var", items)
# make no matches NA
res[rowSums(res) == 0,] <- NA
cbind(data, res)
# data var0 var1 var2 var3 var33 var999
# 1 0 1 2 1 1 1 0 0 0
# 2 0 2 3 1 0 1 1 0 0
# 3 999 0 0 0 0 0 1
# 4 33 0 0 0 0 1 0
# 5 33 0 3 1 0 0 1 1 0
# 6 <NA> NA NA NA NA NA NA
# 7 33 0 3 1 0 0 1 1 0