2016-06-09 131 views
1

我正在研究清理某些數據的解決方案,但並非100%確定最佳解決方案。我找到了一個可行的解決方案,但想知道是否有更簡單的方法(尤其是在試圖擴展它的時候)。我想要做的是分離數據框中的所有元素(用分號分隔),將這些組件中的每一個應用於數據框的元素,然後將結果合併到新的數據框中。下面的例子:跨數據幀循環創建新的數據幀

test <- data.frame(class=c("a1", "a2","a3","a4"), 
     person=c("p1;p3;p4","p2;p4","p4;p5;p6","p1;p5"), 
     stringsAsFactors = F) 

test1 <- c() 
test2 <- c() 

for (i in 1:nrow(test)){ 
    test1 <-append(test1, strsplit(test[i,2],";")[[1]]) 
    test2 <- append(test2, rep(test[i,1],length(strsplit(test[i,2],";")[[1]]))) 
} 

回答

1

我們可以用cSplitsplitstackshape(這裏我提到一個包,並使用一個,而不包括另一個)由分隔符;分裂「人」列,並指定directionlong重塑後的「長」格式分裂。

library(splitstackshape) 
cSplit(test, 'person', ';', 'long') 
# class person 
# 1: a1  p1 
# 2: a1  p3 
# 3: a1  p4 
# 4: a2  p2 
# 5: a2  p4 
# 6: a3  p4 
# 7: a3  p5 
# 8: a3  p6 
# 9: a4  p1 
#10: a4  p5 

或者從base R另一個班輪(不使用任何套餐)

stack(setNames(strsplit(test$person, ";"), test$class))[2:1] 
1

這稍微詳細oneliner會做,如果我明白你到底該怎麼做:

do.call("rbind",apply(test, 1, function(x) expand.grid(x[1], unlist(strsplit(x[2], split=";"))))) 

    Var1 Var2 
1 a1 p1 
2 a1 p3 
3 a1 p4 
4 a2 p2 
5 a2 p4 
6 a3 p4 
7 a3 p5 
8 a3 p6 
9 a4 p1 
10 a4 p5 

我您的原始數據幀中的每一行使用expand.grid,其中包括第一個變量和第二個變量被;分解爲輸入。由於apply是一個列表的結果,我使用do.callrbind將其放回數據框。

1

隨着tidyr

library(dplyr) 
library(tidyr) 

     # separate person into multiple columns 
test %>% separate(person, into = paste0('person', 1:5), fill = 'right') %>% 
    # gather from wide to long 
    gather(key = id, value = person, -class, na.rm = TRUE) %>% 
    # clean up extra column 
    select(-id) 

# class person 
# 1  a1  p1 
# 2  a2  p2 
# 3  a3  p4 
# 4  a4  p1 
# 5  a1  p3 
# 6  a2  p4 
# 7  a3  p5 
# 8  a4  p5 
# 9  a1  p4 
# 11 a3  p6