2013-05-24 1 views
2

데이터 프레임에서 하나의 긴 행을 얻는 사람의 변수 목록이 있습니다.이 레코드를 더 의미있는 형식으로 재구성하는 데 관심이 있습니다. 내 원시 데이터는 다음과 같습니다데이터 프레임에서 하나의 긴 행을 개별 레코드로 변환합니다.

,

df <- data.frame(name1 = "John Doe", email1 = "[email protected]", phone1 = "(444) 444-4444", name2 = "Jane Doe", email2 = "[email protected]", phone2 = "(444) 444-4445", name3 = "John Smith", email3 = "[email protected]", phone3 = "(444) 444-4446", name4 = NA, email4 = "[email protected]", phone4 = NA, name5 = NA, email5 = NA, phone5 = NA) 
df 
#  name1  email1   phone1 name2  email2   phone2 
# 1 John Doe [email protected] (444) 444-4444 Jane Doe [email protected] (444) 444-4445 
#  name3   email3   phone3 name4   email4 phone4 name5 
# 1 John Smith [email protected] (444) 444-4446 NA [email protected]  NA NA 
# email5 phone5 
# 1  NA  NA  

나는 이런 형식으로 구부러 노력하고,

df_transform <- structure(list(name = structure(c(2L, 1L, 3L, NA, NA), .Label = c("Jane Doe", 
"John Doe", "John Smith"), class = "factor"), email = structure(c(3L, 
1L, 4L, 2L, NA), .Label = c("[email protected]", "[email protected]", 
"[email protected]", "[email protected]"), class = "factor"), phone = structure(c(1L, 
2L, 3L, NA, NA), .Label = c("(444) 444-4444", "(444) 444-4445", 
"(444) 444-4446"), class = "factor")), .Names = c("name", "email", 
"phone"), class = "data.frame", row.names = c(NA, -5L)) 
df_transform 
#   name   email   phone 
# 1 John Doe [email protected] (444) 444-4444 
# 2 Jane Doe [email protected] (444) 444-4445 
# 3 John Smith [email protected] (444) 444-4446 
# 4  <NA> [email protected]   <NA> 
# 5  <NA>   <NA>   <NA> 

그것은 다섯 개 기록은 항상 아니라고 추가되어야한다 1에서 99 사이의 숫자가 될 수 있습니다. reshape2melt과`t() 1로 시도했지만 복잡합니다. 내가 모르는 방법을 알고 있다고 상상해보십시오. 당신은 올바른 궤도에있어

답변

2

1) 모양 변경()를 먼저 우리는, names0을 감소 열 이름을주는 열 이름에서 숫자를 벗겨. 그런 다음 우리는 g (email, namephone 열 그룹에 해당하는 세 가지 구성 요소가있는 그룹)로 열을 나눕니다. 그런 다음 reshape (R 기저에서)을 사용하여 길이가 긴 변환을 수행하고 결과로 나오는 긴 데이터 프레임에서 원하는 열을 선택하여 reshape에 의해 자동으로 추가 된 열을 제외합니다. 이 선택 벡터 인 unique(names0)은 원하는 결과로 결과 열을 재정렬합니다.

names0 <- sub("\\d+$", "", names(df)) 
g <- split(names(df), names0) 
reshape(df, dir = "long", varying = g, v.names = names(g))[unique(names0)] 

마지막 라인이 제공 : 여기

  name   email   phone 
1.1 John Doe [email protected] (444) 444-4444 
1.2 Jane Doe [email protected] (444) 444-4445 
1.3 John Smith [email protected] (444) 444-4446 
1.4  <NA> [email protected]   <NA> 
1.5  <NA>   <NA>   <NA> 

2) reshape2 패키지는 reshape2를 이용한 용액이다. rowname 열을 dfmelt에 길게 추가합니다. 그런 다음 variable 열을 이름 부분 (name, email, phone)과 숫자 접미어 부분 (id)으로 분할합니다. 마지막으로 dcast을 사용하여 다시 와이드 형식으로 변환하고 이전과 같은 적절한 열을 선택합니다. 마지막 라인이 제공

library(reshape2) 

m <- melt(data.frame(rowname = 1:nrow(df), df), id = 1) 
mt <- transform(m, 
    variable = sub("\\d+$", "", variable), 
    id = sub("^\\D+", "", variable) 
) 
dcast(mt, rowname + id ~ variable)[, unique(mt$variable)] 

:

 name   email   phone 
1 John Doe [email protected] (444) 444-4444 
2 Jane Doe [email protected] (444) 444-4445 
3 John Smith [email protected] (444) 444-4446 
4  <NA> [email protected]   <NA> 
5  <NA>   <NA>   <NA> 

3) 단순 매트릭스는 재편. 열 이름에서 숫자 접미사를 제거하고 cn을 고유 한 나머지 이름으로 설정하십시오. (cn은 열 이름을 나타냄). 그런 다음 행을행으로 n x 길이 (cn) 행렬로 다시 변형하여 열 이름을 추가합니다.

cn <- unique(sub("\\d+$", "", names(df))) 
matrix(as.matrix(df), nc = length(cn), byrow = TRUE, dimnames = list(NULL, cn)) 

    name   email   phone   
[1,] "John Doe" "[email protected]" "(444) 444-4444" 
[2,] "Jane Doe" "[email protected]" "(444) 444-4445" 
[3,] "John Smith" "[email protected]" "(444) 444-4446" 
[4,] NA   "[email protected]" NA    
[5,] NA   NA    NA  

4) tapply이 문제는 또한 간단한 tapply으로 해결 될 수있다. 이전과 마찬가지로 names0은 숫자 접미사가없는 열 이름입니다. names.suffix은 단지 접미사입니다.이제 tapply를 사용

names0 <- sub("\\d+$", "", names(df)) 
names.suffix <- sub("^\\D+", "", names(df)) 
tapply(as.matrix(df), list(names.suffix, names0), c)[, unique(names0)] 

마지막 줄은 제공 :

name   email   phone   
1 "John Doe" "[email protected]" "(444) 444-4444" 
2 "Jane Doe" "[email protected]" "(444) 444-4445" 
3 "John Smith" "[email protected]" "(444) 444-4446" 
4 NA   "[email protected]" NA    
5 NA   NA    NA 
+0

감사합니다, 나는 당신의 대답을 좋아하고 당신은 오직베이스 -R을 사용하고 있다고 생각합니다. –

+0

'reshape()'의 다양한 인수는 해당 reshape2 솔루션보다 문제에 더 적합하지만 행렬 재 형성과'tapply' 솔루션은 추가 된 것 중 가장 간단한 것일 수 있습니다. –

3

,이 시도 :

library(reshape2) 

# melt it down 
df.melted = melt(t(df)) 
# get rid of the numbers at the end 
df.melted$Var1 = sub('[0-9]+$', '', df.melted$Var1) 

# cast it back 
dcast(df.melted, (seq_len(nrow(df.melted)) - 1) %/% 3 ~ Var1)[,-1] 
#   email  name   phone 
#1 [email protected] John Doe (444) 444-4444 
#2 [email protected] Jane Doe (444) 444-4445 
#3 [email protected] John Smith (444) 444-4446 
#4 [email protected]  <NA>   <NA> 
#5   <NA>  <NA>   <NA> 
+0

감사합니다, 당신이 내가 언급 한 도구를 사용하고 있는지 주셔서 감사합니다. –

관련 문제