簡體   English   中英

從因子級別的子串創建虛擬變量

[英]Creating dummy variables from substrings of factor levels

目標

使用包含NA或由空格分隔的一系列整數的因子變量,我試圖創建一系列虛擬變量(var1,var2,...,vari),如果字符串包含整數i,則取值為1(NOT簡單地說字符i),如果字符串包含NA則為NA,否則為0。

問題

我有點卡住,因為我嘗試使用grep()在字符串中搜索定義每個整數的字符,但這會返回行號而不是boole向量。 此外,搜索“7”返回“77”,“97”等,而不是僅返回“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

你需要使用返回TF而不是grep grepl來返回匹配的值或匹配的位置,並且因為你正在處理字符串,所以最好先從字符而不是因子開始,這里有一些開始如何做它。 重命名變量名稱,因為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

為了處理你的評論中提到的333案例,你可以在grepl中添加一個單詞邊界\\\\b ,它將區分333

使用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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM