2016-12-13 2 views
2

저는 까다로운 질문에 직면 해 있으며 도움이되기를 기뻐합니다.발생시 data.frame의 각 행을 복제하십시오.

ID 구조가 다른 데이터 프레임이 있습니다. 다음과 같은 내용 :

ID 
bbb-5p/mi-98/6134 
abb-4p 
bbb-5p/mi-98 

"/"이 때마다 행을 복제하고 싶습니다. 각 행은 우리가 이것을 "/"발견 한 횟수만큼 복제되어야합니다. 그런 다음 복제 된 행의 이름은 루트 + "/"다음의 문자 여야합니다.

exemple이를 위해 :

ID 
bbb-5p/mi-98/6134 

가 제공해야합니다 또한

ID 
bbb-5p 
bbb-5p-mi-98 
bbb-5p-6134 

내 초기 데이터 프레임을 5 개 변수가 있습니다

[ID, varA, varB, varC, varD] 

그리고 내가 가진 모든 시간을이 "/" 전체 행을 복제하고 싶습니다. 그럼 난

newID   newvarA newvarB newvarC newvarD 
    bbb-5p  varA(1) varB(1) varC(1) varD(1) 
    bbb-5p-mi-98 varA(1) varB(1) varC(1) varD(1) 
    bbb-5p-6134 varA(1) varB(1) varC(1) varD(1) 
    abb-4p  varA(2) varB(2) varC(2) varD(2) 
    bbb-5p  varA(3) varB(3) varC(3) varD(3) 
    bbb-5p-mi-98 varA(3) varB(3) varC(3) varD(3) 

어떤 생각처럼 뭔가 새로운 데이터 프레임을 기대하고있다? 다음과 같은

베드로에게 사전에이를 달성하기

+1

이 중복 질문입니다은 http://stackoverflow.com/questions/30818840/in-r-get-multiple-rows-by-splitting-a-column-using-tidyr-and-reshape2 참조 그리고 http://stackoverflow.com/questions/13773770/split-comma-separated-column-into-separate-rows –

+0

@akrun 이것은 정확한 사기꾼이 아닙니다. 여기서 질문은 단순히 문자열을 분할하고 수직으로 쌓는 것 이상을 포함합니다. – mtoto

+0

@mtoto 오, 알았어, 다시 열어. 제공된 두 링크가이 링크에 링크되어 있다고 생각했습니다. 죄송합니다. – akrun

답변

0

한 가지 방법은 당신을 감사합니다 :

library(dplyr) 
library(tidyr) 
res <- df %>% mutate(i=row_number(), 
        ID = strsplit(ID,split='/')) %>% 
       unnest() %>% 
       group_by(i) %>% 
       mutate(ID=ifelse(ID==first(ID),first(ID),paste(first(ID),ID,sep='-'))) %>% 
       ungroup() %>% select(-i) 
### A tibble: 6 x 1 
##   ID 
##   <chr> 
##1  bbb-5p 
##2 bbb-5p-mi-98 
##3 bbb-5p-6134 
##4  abb-4p 
##5  bbb-5p 
##6 bbb-5p-mi-98 

주 :

  1. 첫째, 나중에 그렇게함으로써 그룹에 인덱스 컬럼 i를 만들 각 "루트"를 그룹화 할 수 있습니다.
  2. strsplit을 사용하여 각 행을 "|"으로 나눕니다.
  3. tidyr::unnest 행 분리.
  4. group_by 생성 된 인덱스 i 다음 행이 첫 번째 행 인 경우 루트 만 반환하십시오. 그렇지 않은 경우 paste을 사용하여 분리 자 "-"이있는 행에 루트를 추가합니다.
  5. 마지막으로 ungroup을 작성하고 작성된 색인 컬럼 i을 제거하십시오.

데이터

df <- structure(list(ID = c("bbb-5p/mi-98/6134", "abb-4p", "bbb-5p/mi-98" 
)), .Names = "ID", row.names = c(NA, -3L), class = "data.frame") 
       ID 
1 bbb-5p/mi-98/6134 
2   abb-4p 
3  bbb-5p/mi-98 
1

를 사용자 지정 기능 lapply()를 사용하여, base R에서이 작업을 수행 할 수 있습니다.lapply() 사용

l <- strsplit(df$ID,"/") 

는 그런 다음 l의 각 요소에 사용자 정의 함수를 적용 :

l_stacked <- lapply(l, function(x) 
      if(length(x) > 1) { 
      c(x[1], paste0(x[1],"-",x[-1])) } 
      else { x }) 

함수를 먼저 확인을 먼저 벡터의 목록의 결과로, "/"에 문자 열을 분할 벡터에 length > 1이 있는지 여부 그럴 경우 모든 요소를 ​​"-"으로 구분 된 첫 번째 요소와 연결합니다. length <= 1 인 경우 문자열에 "/"이 포함되지 않았으므로 그대로 반환됩니다. 마지막으로 을 사용하여 출력을 data.frame으로 변환 할 수 있습니다.

data.frame(ID = unlist(l_stacked)) 
#   ID 
#1  bbb-5p 
#2 bbb-5p-mi-98 
#3 bbb-5p-6134 
#4  abb-4p 
#5  bbb-5p 
#6 bbb-5p-mi-98 
+0

답변 해 주셔서 감사합니다. 이 코드가 작동하는 것처럼 들리지만 ... 요점은이 새로운 ID를 내 data.frame의 다른 변수와 연결하는 방법입니다. – Peter

+0

정교하게 만들 수 있습니까? 이것은 원래의 질문에 언급되어 있지 않습니다. – mtoto

+0

내 초기 데이터 프레임에 5 개의 변수 [ID, varA, varB, varC, varD]가 있다고 가정 해 보겠습니다. 나가 의미하는 것은, 나가 이것을 할 때마다 "/"나는 줄을 복제하고 싶으면이다. 그러나 전체 행을 유지하십시오. 그런 다음 새로운 데이터 프레임을 [newID (1), varA (1), varB (1), varC (1), varD (1)] ..... [newID (n) varA (n), varB (n), varC (n), varD (n)] ... 더 명확한가요? – Peter

0

여기서는 data.table을 사용하는 옵션 중 하나입니다. 'data.frame'을 'data.table'(setDT(df1, ..)로 변환하고 'rn'으로 그룹화 된 rownames의 열을 만들고 'ID'를 /으로 분할하고 행의 시퀀스를 반복하며 분할 요소를 기반으로 paste 색인에.

library(splitstackshape) 
library(data.table) 
setDT(df1, keep.rownames=TRUE)[, unlist(strsplit(ID, "/")), 
     by = rn][, .(ID=sapply(seq_len(.N), function(i) 
      paste(V1[unique(c(1,i))], collapse="-"))) , rn] 

또는 dplyr/tidyr/tibble과 옵션을 선택합니다. tibble::rownames_to_column을 사용하여 rownames 열을 만들고 'rn'으로 그룹화 된 separate_rows으로 행을 구분하고, 길이가 0 인 조건으로 요소를 입력하고 'rn'열을 제거하여 'ID'를 paste으로 만듭니다.

library(dplyr) 
library(tidyr) 
library(tidyr) 
rownames_to_column(df1, var = "rn") %>% 
     separate_rows(ID, sep="/") %>% 
     group_by(rn) %>% 
     mutate(ID = if(n()>1) c(ID[1], paste(ID[1], ID[-1], sep="-")) else ID) %>% 
     ungroup() %>% 
     select(-rn) 
#   ID 
#  <chr> 
#1  bbb-5p 
#2 bbb-5p-mi-98 
#3 bbb-5p-6134 
#4  abb-4p 
#5  bbb-5p 
#6 bbb-5p-mi-98