2017-01-16 9 views
1

このスレッドは見つかりませんでしたFind rows in dataframe with maximum values grouped by values in another column解決策の1つが議論されました。私は再帰的に最大量の行インデックスを見つけるためにこのソリューションを使用しています。しかし、私のソリューションは非常に醜いです - ベクトル化ではなく非常に手続き的です。ここで最大値に対応するインデックスを見つける

は私のダミーデータです:

dput(Data) 

structure(list(Order_Year = c(1999, 1999, 1999, 1999, 1999, 1999, 
1999, 2000, 2000, 2001, 2001, 2001, 2001, 2001, 2001, 2001, 2002, 
2002, 2002, 2002), Ship_Year = c(1997, 1998, 1999, 2000, 2001, 
2002, NA, 1997, NA, 1997, 1998, 1999, 2000, 2001, 2002, NA, 1997, 
1998, 1999, 2000), Yen = c(202598.2, 0, 0, 0, 0, 0, 2365901.62, 
627206.75998, 531087.43, 122167.02, 143855.55, 0, 0, 0, 0, 53650.389998, 
17708416.3198, 98196.4, 31389, 0), Units = c(37, 1, 8, 5, 8, 
8, 730, 99, 91, 195, 259, 4, 1, 3, 3, 53, 3844, 142, 63, 27)), .Names = c("Order_Year", 
"Ship_Year", "Yen", "Units"), row.names = c(NA, 20L), class = "data.frame") 

私はYenUnitsが与えられたOrder_Yearのために最大であるためShip_Yearを知りたいです。

は、ここに私が試したものです:

a<-do.call("rbind", by(Data, Data$Order_Year, function(x) x[which.max(x$Yen), ])) 
rownames(a)<-NULL 
a$Yen<-NULL 
a$Units<-NULL 
#a has Ship_Year for which Yen is max for a given Order_Year 
names(a)[2]<-"by.Yen" 
#Now I'd find max year by units 
b<-do.call("rbind", by(Data, Data$Order_Year, function(x) x[which.max(x$Units), ])) 
rownames(b)<-NULL 
b$Yen<-NULL 
b$Units<-NULL 
#b has Ship_Year for which Units is max for a given Order_Year 
names(b)[2]<-"by.Qty" 
c<-a %>% left_join(b) 

予想される出力は次のようになります。

c 
    Order_Year by.Yen by.Qty 
1  1999  NA  NA 
2  2000 1997 1997 
3  2001 1998 1998 
4  2002 1997 1997 

私が期待される出力を得ながら、上記の方法は非常に不格好です。これを処理するより良い方法はありますか?

答えて

4

which.maxはdplyrのグループ化でうまく動作:

library(dplyr) 

Data %>% group_by(Order_Year) %>% 
    summarise(by.Yen = Ship_Year[which.max(Yen)], 
       by.Units = Ship_Year[which.max(Units)]) 

## # A tibble: 4 × 3 
## Order_Year by.Yen by.Units 
##  <dbl> <dbl> <dbl> 
## 1  1999  NA  NA 
## 2  2000 1997  1997 
## 3  2001 1998  1998 
## 4  2002 1997  1997 
2

我々はdata.tableを使用することができます。 'data_frame'を 'order_Year'でグループ化した 'data.table'(setDT(Data))に変換し、最大値のインデックスを 'Yen'、 'Units'にmatch、サブセットに 'Ship_Year'要約出力

library(data.table) 
setDT(Data)[,.(by.Yen = Ship_Year[match(max(Yen), Yen)], 
     by.Units = Ship_Year[match(max(Units), Units)]) , Order_Year] 
# Order_Year by.Yen by.Units 
#1:  1999  NA  NA 
#2:  2000 1997  1997 
#3:  2001 1998  1998 
#4:  2002 1997  1997 

を返すために、そのインデックスに基づいて、代わりに個別にこれを行うには多くの列がある場合、我々はを通じて、「ORDER_YEAR」によってグループ化され、.SDcolsでループを関心の列を指定することができますData.tableのサブセット(.SD)最大値のインデックスunlistlist出力を取得し、そのインデックスに基づいて 'Ship_Year'をサブセット化してに変換しますカラムの(as.list)とセット名が 'by.Units'

setnames(setDT(Data)[, as.list(Ship_Year[unlist(lapply(.SD, 
    which.max))]), Order_Year, .SDcols = c("Yen", "Units")], 
       2:3, c("by.Yen", "by.Units"))[] 
# Order_Year by.Yen by.Units 
#1:  1999  NA  NA 
#2:  2000 1997  1997 
#3:  2001 1998  1998 
#4:  2002 1997  1997 
+0

@akrun - ありがとうございました。手順を説明してもらえますか?あなたのコードを実行しようとしましたが、実際には理解できませんでした。 – watchtower

+1

@watchtower説明を更新しました。あなたが助けてくれてありがとう。 – akrun

+0

シンプルさのためにAlistaireの答えを答えにすることを考えました。ご理解頂けるとありがたいです。 – watchtower

2

用いて基地R 'by.Yen' とする

a1 <- with(df1, 
      by(data = df1, 
       INDICES = Order_Year, 
       FUN  = function(x) list(Yen = x$Ship_Year[which.max(x$Yen)], 
             Units = x$Ship_Year[which.max(x$Units)]))) 

do.call("rbind", lapply(a1, function(x) data.frame(x))) 
#  Yen Units 
# 1999 NA NA 
# 2000 1997 1997 
# 2001 1998 1998 
# 2002 1997 1997 

データ:

df1 <- structure(list(Order_Year = c(1999, 1999, 1999, 1999, 1999, 1999, 1999, 
            2000, 2000, 2001, 2001, 2001, 2001, 2001, 
            2001, 2001, 2002, 2002, 2002, 2002), 
         Ship_Year = c(1997, 1998, 1999, 2000, 2001, 2002, NA, 
            1997, NA, 1997, 1998, 1999, 2000, 2001, 
            2002, NA, 1997, 1998, 1999, 2000), 
         Yen = c(202598.2, 0, 0, 0, 0, 0, 2365901.62, 627206.75998, 
           531087.43, 122167.02, 143855.55, 0, 0, 0, 0, 
           53650.389998, 17708416.3198, 98196.4, 31389, 0), 
         Units = c(37, 1, 8, 5, 8, 8, 730, 99, 91, 195, 259, 4, 
           1, 3, 3, 53, 3844, 142, 63, 27)), 
       .Names = c("Order_Year", "Ship_Year", "Yen", "Units"), 
       row.names = c(NA, 20L), 
       class = "data.frame") 
+0

編集された答えが正しい解を与える。以前の集計関数とその出力は常に機能せず、期待される結果と一致する出力は偶然です。希望どおりのパッケージがなくても役立ちます – Sathish

関連する問題