2016-09-13 62 views
5

我有興趣獲取data.frame的列,其中列中的值是管道分隔的,並從管道分隔的值中創建虛擬變量。將具有管道分隔數據的列轉換爲虛擬變量

例如:

比方說,我們開始與

df = data.frame(a = c("Ben|Chris|Jim", "Ben|Greg|Jim|", "Jim|Steve|Ben")) 

> df 
       a 
1 Ben|Chris|Jim 
2 Ben|Greg|Jim 
3 Jim|Steve|Ben 

我感興趣的結尾了:

df2 = data.frame(Ben = c(1, 1, 1), Chris = c(1, 0, 0), Jim = c(1, 1, 1), Greg = c(0, 1, 0), 
       Steve = c(0, 0, 1)) 
> df2 
    Ben Chris Jim Greg Steve 
1 1  1 1 0  0 
2 1  0 1 1  0 
3 1  0 1 0  1 

我不知道提前多少潛在價值有在領域內。在上面的例子中,變量「a」可以包含1個值或10個值。假定它是一個合理的數字(即,可能的值爲<)。

任何好的方法來做到這一點?

回答

6

的另一種方法是使用cSplit_esplitstackshape包。

按列afill將數據幀拆分爲0和drop原始列。

library(splitstackshape) 
cSplit_e(df, "a", "|", type = "character", fill = 0, drop = T) 

# a_Ben a_Chris a_Greg a_Jim a_Steve 
#1  1  1  0  1  0 
#2  1  0  1  1  0 
#3  1  0  0  1  1 
+1

什麼是一個偉大的發現。 –

+1

許多偉大的答案 - 謝謝大家。我喜歡這個最好的,因爲它感覺最簡單。謝謝! – dreww2

6

下面是使用dplyrtidyr一個選項:

library(dplyr) 
library(tidyr) 
df %>% tibble::rownames_to_column(var = "id") %>% 
     mutate(a = strsplit(as.character(a), "\\|")) %>% 
     unnest() %>% table() 

# a 
# id Ben Chris Greg Jim Steve 
# 1 1  1 0 1  0 
# 2 1  0 1 1  0 
# 3 1  0 0 1  1 

在基礎R的類似物是:

df$a <- as.character(df$a) 
s <- strsplit(df$a, "|", fixed=TRUE) 
table(id = rep(1:nrow(df), lengths(s)), v = unlist(s)) 

數據:

df = data.frame(a = c("Ben|Chris|Jim", "Ben|Greg|Jim", "Jim|Steve|Ben")) 
2

我們可以分裂的 'a' 的列

library(qdapTools) 
mtabulate(strsplit(as.character(df$a), "|", fixed = TRUE)) 
# Ben Chris Greg Jim Steve 
#1 1  1 0 1  0 
#2 1  0 1 1  0 
#3 1  0 0 1  1 
0

這裏使用後mtabulateqdapTools是在基礎R

# get unique set of names 
myNames <- unique(unlist(strsplit(as.character(df$a), split="\\|"))) 
# get indicator data.frame 
setNames(data.frame(lapply(myNames, function(i) as.integer(grepl(i, df$a)))), myNames) 

返回

Ben Chris Jim Greg Steve 
1 1  1 1 0  0 
2 1  0 1 1  0 
3 1  0 1 0  1 

的方法該第一行使用strsplit來產生分割在管道「|」上的名稱列表,unlistunique產生獨特名稱的向量。第二行使用lapply來遍歷這些名稱,並使用grepl來搜索名稱,其中as.integer將其轉換爲二進制整數。返回的列表被轉換爲一個data.frame並給出列名爲setNames

相關問題