2016-06-11 9 views
2

私は誰かが私を助けてくれることを願っています。基本的にデータ操作です。私は10の列、 "id"と3組の同様の変数、 "type"、 "startdate"、 "enddate"からなる大きなデータセットを持っています。例を以下に示す。R:行ごとに属性値(日付)に基づいてグループソートを行う方法は?

id type1 startdate1 enddate1 type2 startdate2 enddate2 type3 startdate3 
1 1  A 2006-08-20 2006-12-06  W 2006-08-01 2007-08-29  P 2007-08-18 
2 2  A 2006-01-05 2007-07-02 NA   NA   NA  Q 2008-01-15 

    enddate3 
1 2007-09-27 
2 2008-02-07 

Iは、次の洗浄とのデータセットをソートし得るしたい:私は「STARTDATE」に従ってため、すべての行/観察を昇順にソートしたい

id type1 startdate1 enddate1 type2 startdate2 enddate2 type3 startdate3 
1 1  W 2006-08-01 2007-08-29  A 2006-08-20 2006-12-06  P 2007-08-18 
2 2  A 2006-01-05 2007-07-02  Q 2008-01-15 2008-02-07 NA   NA 

enddate3 
1 2007-09-27 
2 NA    

を。したがって、行1の場合、第2のグループまたは変数のセットは、第1のグループの「開始日」(2006-08-20)と比較して、より早い「開始日」(2006-08-01)を有するので、最初のグループポジション。

2行目は、すべてのNAsを最後までプッシュしたいと思います。

これを効率的に行うためのヒントを教えてください。

"startdate"と "enddate"のデータ型を数値に変換する必要がありますか?もし私がすれば、 "NA"はどのように扱うべきですか?

すべての3セットの(type、startdate、enddate)にpaste()関数を適用することをお勧めしますか?

ありがとうございました!前もって感謝します!

答えて

1

dplyrtidyrを使用する解決方法は、データセットをロングフォーマットに変換し、必要に応じて並べ替えを行い、その後ワイドフォーマットに変換することに依存します。長い形式に変換すると値はcharacterになりますので、列の種類を再適用する必要があります。ミッコMarttilaとしてではなく、非標準のライブラリを使用せずに

library(tidyr) 
library(dplyr) 

df <- read.table(header = TRUE, text = " 
id type1 startdate1 enddate1 type2 startdate2 enddate2 type3 startdate3 enddate3 
1  A 2006-08-20 2006-12-06  W 2006-08-01 2007-08-29  P 2007-08-18 2007-09-27 
2  A 2006-01-05 2007-07-02 NA   NA   NA  Q 2008-01-15 2008-02-07 
") 

df %>% 
    gather(key, value, -id) %>% # convert to long format 
    extract(key, c("var", "seq"), "(.*)(\\d)") %>% # extract sequence number 
    spread(var, value) %>% # spread to wide format by id and sequence 
    group_by(id) %>% 
    arrange(startdate) %>% # sort seq by startdate in id groups 
    mutate(seq = 1:n()) %>% # calculate new sequence order 
    gather(key, value, -id, -seq) %>% # convert to long format 
    transmute(var = paste0(key, seq), value) %>% # generate wide format names 
    spread(var, value) %>% # spread to back to wide format 
    select(one_of(names(df))) %>% # restore original column order 
    mutate_each("as.Date", one_of(grep("date", names(df), value = TRUE))) 
     # reapply date type to original date variables 

#  Source: local data frame [2 x 10] 
#  Groups: id [2] 
#  
#   id type1 startdate1 enddate1 type2 startdate2 enddate2 type3 startdate3 enddate3 
#  (int) (chr)  (date)  (date) (chr)  (date)  (date) (chr)  (date)  (date) 
#  1  1  W 2006-08-01 2007-08-29  A 2006-08-20 2006-12-06  P 2007-08-18 2007-09-27 
#  2  2  A 2006-01-05 2007-07-02  Q 2008-01-15 2008-02-07 NA  <NA>  <NA> 
1

plyrパッケージのrbind.fillを使用できます。さて、その関数は、列名に従って結合するのに十分なインテリジェントです - 私たちはそれを望んでいません。観測データを各行に転送するには、NAを削除して元のデータフレームの名前を新しいベクトルに適用します。

library(plyr) 

df <- data.frame("obs" = seq(3), 
       type1 = c(2,2,NA),date1 = c("date11","date21",NA), 
       type2 = c(3,NA,5),date2 = c("date12",NA,"date31"), 
       type3 = c(4,3,1), date3 = c("date13","date22","date32"), 
       type4 = c(4,4,NA),date4 = c("date14","date23",NA)) 
df 
# obs type1 date1 type2 date2 type3 date3 type4 date4 
# 1 1  2 date11  3 date12  4 date13  4 date14 
# 2 2  2 date21 NA <NA>  3 date22  4 date23 
# 3 3 NA <NA>  5 date31  1 date32 NA <NA> 

newdf <- sapply(1:nrow(df), function(i){ 
    newrow <- (df[i,!is.na(df[i,])])    ## Remove NA's 
    names(newrow) <- names(df)[1:length(newrow)] ## Apply names 

    newrow          ## Output 
}) 

rbind.fill(newdf) 
# obs type1 date1 type2 date2 type3 date3 type4 date4 
# 1 1  2 date11  3 date12  4 date13  4 date14 
# 2 2  2 date21  3 date22  4 date23 NA <NA> 
# 3 3  5 date31  1 date32 NA <NA> NA <NA> 

注意:このコードはtype場合に動作し、日付が観測されたまたはNAのいずれかと一緒に来ます。

+0

は、私はあなたがプッシュ日付に依存するようにしたいJUST *のこぎりを*。私は本質的にあなたが2つの質問をしていると思っています - 1):プッシュする方法と2):ソートする方法。私は最初の質問に答えただけです。 – Therkel

+0

ありがとう!私のデータセットは非常に疎であるので、これは非常に便利なようです。そして、私は実際にはNAを右に押す必要があります。 – HNSKD

2

同じアプローチ:

> ## use vectors of class Date 
> df[c(3,4,6,7,9,10)] <- lapply(df[c(3,4,6,7,9,10)], as.Date) 

> ## reshape to long format 
> df.1 <- reshape(df, idvar=1, 
+     varying=list(c(2,5,8), c(3,6,9), c(4,7,10)), 
+     v.names=c('type', 'startdate', 'enddate'), 
+     times=c(1,2,3), timevar='group', direction='long') 
> df.1 
#  id group type startdate enddate 
# 1.1 1  1 A 2006-08-20 2006-12-06 
# 2.1 2  1 A 2006-01-05 2007-07-02 
# 1.2 1  2 W 2006-08-01 2007-08-29 
# 2.2 2  2 <NA>  <NA>  <NA> 
# 1.3 1  3 P 2007-08-18 2007-09-27 
# 2.3 2  3 Q 2008-01-15 2008-02-07 

> ## reset group variable according to startdate 
> df.1$group <- with(df.1, unsplit(lapply(split(startdate, id), order), id)) 
> df.1 
#  id group type startdate enddate 
# 1.1 1  2 A 2006-08-20 2006-12-06 
# 2.1 2  1 A 2006-01-05 2007-07-02 
# 1.2 1  1 W 2006-08-01 2007-08-29 
# 2.2 2  3 <NA>  <NA>  <NA> 
# 1.3 1  3 P 2007-08-18 2007-09-27 
# 2.3 2  2 Q 2008-01-15 2008-02-07 

> ## back to wide format 
> df.2 <- reshape(df.1[order(df.1$group), ], idvar=1, 
+     v.names=c('type', 'startdate', 'enddate'), timevar='group', 
+     direction='wide') 

> ## sort by id 
> df.2 <- df.2[order(df.2$id), ] 

> df.2 
#  id type.1 startdate.1 enddate.1 type.2 startdate.2 enddate.2 type.3 
# 1.2 1  W 2006-08-01 2007-08-29  A 2006-08-20 2006-12-06  P 
# 2.1 2  A 2006-01-05 2007-07-02  Q 2008-01-15 2008-02-07 <NA> 
#  startdate.3 enddate.3 
# 1.2 2007-08-18 2007-09-27 
# 2.1  <NA>  <NA> 
関連する問題