2016-05-03 12 views
1

私はdata.frameを集計したいと思います。ここR:2列以上のdata.frame行の集計(中央値)

はサンプルデータである。

data <- structure(list(Charge = c(210133L, 210133L, 210133L, 210152L, 
            210152L, 210152L, 210152L, 210180L, 210180L, 210180L), Seq = c(1L, 
                             2L, 3L, 1L, 2L, 3L, 4L, 1L, 2L, 2L), x = c(NA, 1.5, 2, 
                                         1.5, 1, 0.67, 1.17, 1, 1, 1), y = c(0.5, 0.5, 1, NA, 0.5, 
                                                    0.5, 0.5, 0.5, 0.5, 0.5)), .Names = c("Charge", "Seq", 
                                                              "x", "y"), row.names = c(NA, 10L), class = "data.frame") 

*説明(上記と同じデータ、異なるフォーマット)の場合:xおよびy列の行の

Charge Seq x y 
1 210133 1 NA 0.5 
2 210133 2 1.50 0.5 
3 210133 3 2.00 1.0 
4 210152 1 1.50 NA 
5 210152 2 1.00 0.5 
6 210152 3 0.67 0.5 
7 210152 4 1.17 0.5 
8 210180 1 1.00 0.5 
9 210180 2 1.00 0.5 
10 210180 2 1.00 0.5 

中央値は、配列のために実行されなければなりません一意の充電ごとに> 1。

そのため、このサンプルデータのための例えば、私が取得したい配列> 1のためのxとyの列の中央値で追加の行です:

 Charge Seq x y 
    1 210133 1 NA 0.5 
    2 210133 2 1.50 0.5 
    3 210133 3 2.00 1.0 
    4 210133 >1 1.75 0.75 #here is additional row with median of x and y 
    4 210152 1 1.50 NA 
    5 210152 2 1.00 0.5... 

助けてくれてありがとう!

答えて

2

data.tableを使用できます。 "data.frame"を "data.table"(setDT(data))に変換し、 "Charge"でグループ化し、列(lapply(.SD,...)をループし、 'i'(Seq >1)の条件に基づいて.SDcolsに指定された列のを取得します。 )、値 "> 1"の 'Seq'列を作成します。新しいデータとともに元のデータをlistに置き、rbindを使用してデータセットを結合し、必要に応じてorderを使用します。

library(data.table) 
setDT(data) 
res <- data[Seq > 1L, lapply(.SD, median, na.rm=TRUE), 
      by = Charge, .SDcols = x:y][, Seq := ">1"][] 
ans <- setorder(rbind(data, res), Charge, Seq) 
# Charge Seq x y 
# 1: 210133 1 NA 0.50 
# 2: 210133 2 1.50 0.50 
# 3: 210133 3 2.00 1.00 
# 4: 210133 >1 1.75 0.75 
# 5: 210152 1 1.50 NA 
# 6: 210152 2 1.00 0.50 
# 7: 210152 3 0.67 0.50 
# 8: 210152 4 1.17 0.50 
# 9: 210152 >1 1.00 0.50 
#10: 210180 1 1.00 0.50 
#11: 210180 2 1.00 0.50 
#12: 210180 2 1.00 0.50 
#13: 210180 >1 1.00 0.50 

我々は元のデータセットにcharacterに「配列」のclassを変換dplyrを使用して同様のオプション。次に、の「Seq」が1でなく、「Charge」でグループ化されている場合、summarise_eachの列のmedianを取得し、出力「Seq」に新しい列を作成し、元のデータをbind_rows 、必要であればorder

library(magrittr) 
library(dplyr) 
data %<>% 
    mutate(Seq = as.character(Seq)) 

data %>% 
    filter(Seq!="1") %>% 
    group_by(Charge) %>% 
    summarise_each(funs(median=median(., na.rm=TRUE)), x:y) %>% 
    mutate(Seq = ">1") %>% 
    bind_rows(data, .) %>% 
    mutate(Seq = factor(Seq, levels = c(unique(data$Seq), ">1"))) %>% 
    arrange(Charge, Seq) 
+1

おかげで、それは魔法のように動作します! –

2

data.tableを使用して同じことを別の方法:

library(data.table) 

setDT(data) 

test <- function(x){ 
    seq.gt.1 <- which(x$Seq > 1) 

    median.1 <- median(x$x[seq.gt.1],na.rm=T) 
    median.2 <- median(x$y[seq.gt.1],na.rm=T) 

    return (rbind(x,data.table(Seq='>1',x=median.1,y=median.2))) 
} 

data[,test(.SD),by=Charge] 

## Charge Seq x y 
##1: 210133 1 NA 0.50 
##2: 210133 2 1.50 0.50 
##3: 210133 3 2.00 1.00 
##4: 210133 >1 1.75 0.75 
##5: 210152 1 1.50 NA 
##6: 210152 2 1.00 0.50 
##7: 210152 3 0.67 0.50 
##8: 210152 4 1.17 0.50 
##9: 210152 >1 1.00 0.50 
##10: 210180 1 1.00 0.50 
##11: 210180 2 1.00 0.50 
##12: 210180 2 1.00 0.50 
##13: 210180 >1 1.00 0.50 
+1

答えをありがとう!あなたのコードは完璧に動作します –

関連する問題