2015-12-23 14 views
7

Ich möchte doppelte Zeilen aus einem Datenrahmen entfernen, der durch verschiedene FATORS und Bedingungen, wie höchsten Mittelwert oder SD, geschichtet ist.Entfernen Sie doppelte Zeilen abhängig von Faktor

Einige Daten, a ist der Faktor und die ID für die Zeilen.

set.seed(13654) 
a<- sort(c(1,1,4,1,2,3,2,3,1,5)) 
b<- matrix(runif(100,min = 6,max = 14),nrow = 10) 
c<- data.frame(a,b) 

Zum Beispiel möchte ich den endgültigen Datensatz in den Zeilen mit dem höchsten Mittelwert reduzieren.

# calculate means per row 
gr <- cbind(a,M=rowMeans(c[,-1])) 
# get rows stratified by a with highest mean: 
gr1 <- aggregate(M~a,gr,which.max) 
gr1 
    a M 
1 1 3 
2 2 2 
3 3 1 
4 4 1 
5 5 1 

Somit wird die dritte Reihe des Faktors Ebene 1, die zweite Zeile des Faktors Ebene 2, ... sollen in den neuen Datenrahmen aufgenommen werden. Ich möchte Schleifen vermeiden. Was ich versuchte, ist split die Daten und dann lapply verwenden, aber nicht so weit gearbeitet.

cl <- split(c,a) 
# this function does not work it will select not the correct rows. 
lapply(cl, "[", gr1,) 

Mein Endziel ist eine Funktion wie folgt aus:

remove.dupl <- function(data,factor,method=c(highest.mean,highest.sd,lowest.sd,...)) 

Können Sie einige tipps oder eine Lösung für mein Problem. Nach meinem Workflow benötige ich ein "How-to", um "[" korrekt mit lapply zu verwenden, um verschiedene Zeilen aus einer Liste von Datenrahmen auszuwählen.

Antwort

2

Mit dem data.table Paket, würde ich es Ansatz wie folgt:

library(data.table) 
# method 1: 
setDT(cc)[, `:=` (rn = 1:.N, wm = which.max(rowMeans(.SD))), a][rn==wm] 
# method 2: 
setDT(cc)[, wm := frank(1/rowMeans(.SD), ties.method="first"), a][wm==1] 

die gibt:

a  X1  X2  X3  X4  X5  X6  X7  X8  X9  X10 wm rn 
1: 1 13.946254 7.302729 9.406389 8.924367 8.129423 10.174735 6.547805 11.618872 12.84100 9.494790 3 3 
2: 2 13.606555 12.798149 11.261258 12.991822 12.875935 11.199411 8.551149 10.377451 13.63219 13.643163 2 2 
3: 3 6.820769 13.748507 11.630297 11.559873 6.196406 8.925419 11.230415 10.584249 10.41442 6.821673 1 1 
4: 4 8.418767 10.673998 6.693021 11.101287 7.855519 9.106210 12.279536 6.925023 6.92334 10.279204 1 1 
5: 5 11.529072 7.940031 10.746172 8.535466 13.703122 12.294424 11.362498 11.256843 13.95535 13.264835 1 1 

In Basis R Sie tun können:

cc$rm <- apply(cc[,-1], 1, mean) 
cc$wm <- ave(cc$rm, cc$a, FUN = function(x) max(x)==x) 
cc[cc$wm == 1,] 

, die gibt:

a  X1  X2  X3  X4  X5  X6  X7  X8  X9  X10  rm wm 
3 1 13.946254 7.302729 9.406389 8.924367 8.129423 10.174735 6.547805 11.618872 12.84100 9.494790 9.838637 1 
6 2 13.606555 12.798149 11.261258 12.991822 12.875935 11.199411 8.551149 10.377451 13.63219 13.643163 12.093708 1 
7 3 6.820769 13.748507 11.630297 11.559873 6.196406 8.925419 11.230415 10.584249 10.41442 6.821673 9.793203 1 
9 4 8.418767 10.673998 6.693021 11.101287 7.855519 9.106210 12.279536 6.925023 6.92334 10.279204 9.025591 1 
10 5 11.529072 7.940031 10.746172 8.535466 13.703122 12.294424 11.362498 11.256843 13.95535 13.264835 11.458781 1 

Als Antwort auf Ihren Kommentar: Alternativ können Sie die rank Funktion innerhalb ave verwenden:

# duplicate the row for which 'max(x)==x' for the first group 
cc <- rbind(cc,cc[3,]) 

cc$wm2 <- ave(cc$rm, cc$a, FUN = function(x) rank(-x, ties.method = "first")) 
cc[cc$wm2 == 1,] 

die gibt:

a  X1  X2  X3  X4  X5  X6  X7  X8  X9  X10  rm wm wm2 
3 1 13.946254 7.302729 9.406389 8.924367 8.129423 10.174735 6.547805 11.618872 12.84100 9.494790 9.838637 1 1 
6 2 13.606555 12.798149 11.261258 12.991822 12.875935 11.199411 8.551149 10.377451 13.63219 13.643163 12.093708 1 1 
7 3 6.820769 13.748507 11.630297 11.559873 6.196406 8.925419 11.230415 10.584249 10.41442 6.821673 9.793203 1 1 
9 4 8.418767 10.673998 6.693021 11.101287 7.855519 9.106210 12.279536 6.925023 6.92334 10.279204 9.025591 1 1 
10 5 11.529072 7.940031 10.746172 8.535466 13.703122 12.294424 11.362498 11.256843 13.95535 13.264835 11.458781 1 1 

HINWEIS: Ich umbenannt den Datenrahmen zu cc, da es nicht besser, eine Funktionsname als Name für den Datenrahmen

+0

Vielen Dank, aber ich ziehe eine Basis R Lösungen. Aber ich behalte das im Hinterkopf. – Jimbou

+1

@Jimbou np, hinzugefügt eine alternative Basis R-Lösung sowie – Jaap

+0

Wie würden Sie Ihre'Ave'-Funktion zu optimieren, wenn Sie doppelte entfernen müssen? Z.B. Das 'max (x) == x 'gibt nur' TRUE' oder mehr als ein 'TRUE' zurück. – Jimbou

4

die by() Funktion Versuchen zu verwenden:

set.seed(13654) 
a <- sort(c(1,1,4,1,2,3,2,3,1,5)) 
b <- matrix(runif(100,min = 6,max = 14),nrow = 10) 
c <- data.frame(a,b) 
myfun <- function(x) which.max(rowMeans(x))     # just replicating your example, you could define other functions here 
d <- by(data = c, INDICES = c$a, function(x) x[myfun(x), ]) # use by() to select rows, based on myfun() 
d <- do.call(rbind, d)          # turn result of by() function into a data frame 
+0

Gute Verwendung von 'by'. Plus eins. – akrun

Verwandte Themen