studio - script acp r




Ne conservez que la valeur min pour chaque niveau de facteur (6)

Avec plyr , j'utiliserais:

ddply(df, .var = "f", .fun = function(x) {
    return(subset(x, v1 %in% min(v1)))
    }
)

Faites un essai et voyez si cela retourne ce que vous voulez.

J'ai des problèmes qui me dérangent depuis un certain temps ... J'espère que tout le monde ici pourra m'aider.

J'ai le bloc de données suivant

f <- c('a','a','b','b','b','c','d','d','d','d')
v1 <- c(1.3,10,2,10,10,1.1,10,3.1,10,10)
v2 <- c(1:10)
df <- data.frame(f,v1,v2)

f est un facteur; v1 et v2 sont des valeurs. Pour chaque niveau de f, je veux seulement garder une ligne: celle qui a la plus petite valeur de v1 dans ce niveau de facteur.

f   v1  v2
a   1.3 1
b   2   3
c   1.1 6
d   3.1 8

J'ai essayé différentes choses avec des agrégats, sans problème, sans problème, mais rien ne semble fonctionner. Pour toutes suggestions, je serais très reconnaissant.


C'est le moyen le plus simple de filtrer les valeurs minimales de v1 par groupes de f :

require(dplyr)
df %>%
  group_by(f) %>%
  filter(v1 == min(v1))

#Source: local data frame [4 x 3]
#Groups: f
#
#  f  v1 v2
#1 a 1.3  1
#2 b 2.0  3
#3 c 1.1  6
#4 d 3.1  8

En cas de liens dans v1 , cela entraînerait plusieurs lignes par groupe de f . Si vous voulez éviter cela, vous pouvez utiliser:

df %>% 
  group_by(f) %>% 
  filter(rank(v1, ties.method= "first") == 1)

De cette façon, vous n’obtiendrez que la première ligne en cas de liens. Vous pouvez également utiliser ties.method = "random" ou d'autres, comme décrit dans le fichier d'aide.


Je suis désolé, mon pouvoir de penser est épuisé et cette solution laide est tout ce que je peux trouver à presque 1 heure du matin.

lapply(split(df, df$f), FUN = function(x) {
            vec <- which(x[3] == min(x[3]))
            return(x[vec, ])
        })

Une autre méthode consiste à utiliser l’ order et les !duplicated , mais vous n’obtiendrez que le premier sur les liens.

df2 <- df[order(df$f,df$v1),]
df2[!duplicated(df2$f),]

  f  v1 v2
1 a 1.3  1
3 b 2.0  3
6 c 1.1  6
8 d 3.1  8

Les temps

f1<-function(){df2<-df[order(df$f,df$v1),]
df2[!duplicated(df2$f),]}

f2<-function(){df2<-df[order(df$v1),]
df2[!duplicated(df2$f),]}

f3<-function(){df[ df$v1 == ave(df$v1, df$f, FUN=min), ]}

library(rbenchmark)
> benchmark(f1(),f2(),f3())
  test replications elapsed relative user.self sys.self user.child sys.child
1 f1()          100   38.16 7.040590     36.66     1.48         NA        NA
2 f2()          100   20.54 3.789668     19.30     1.23         NA        NA
3 f3()          100    5.42 1.000000      4.96     0.46         NA        NA

Une solution data.table .

library(data.table)
DT <- as.data.table(df)
DT[,.SD[which.min(v1)], by = f]

##   f  v1 v2
## 1: a 1.3  1
## 2: b 2.0  3
## 3: c 1.1  6
## 4: d 3.1  8

Ou plus efficacement

DT[DT[,.I[which.min(v1)],by=f][['V1']]]

une analyse comparative

f <- rep(letters[1:20],100000)
v1 <- rnorm(20*100000)
v2 <- 1:(20*100000)
df <- data.frame(f,v1,v2)
DT <- as.data.table(df)
f1<-function(){df2<-df[order(df$f,df$v1),]
               df2[!duplicated(df2$f),]}

f2<-function(){df2<-df[order(df$v1),]
               df2[!duplicated(df2$f),]}

f3<-function(){df[ df$v1 == ave(df$v1, df$f, FUN=min), ]}


f4 <- function(){DT[,.SD[which.min(v1)], by = f]}

f5 <- function(){DT[DT[,.I[which.min(v1)],by=f][['V1']]]}

library(microbenchmark)
microbenchmark(f1(),f2(),f3(),f4(), f5(),times = 5)
# Unit: milliseconds
# expr       min        lq    median        uq       max neval
# f1() 3254.6620 3265.4760 3286.5440 3411.4054 3475.4198     5
# f2() 1630.8572 1639.3472 1651.5422 1721.4670 1738.6684     5
# f3()  172.2639  174.0448  177.4985  179.9604  184.7365     5
# f4()  206.1837  209.8161  209.8584  210.4896  210.7893     5
# f5()  105.5960  106.5006  107.9486  109.7216  111.1286     5

L’approche .I est la .SD gagnante ( la version # 2330 devrait permettre d’ .SD rapidement l’élégance de l’approche .SD ).


Voici une solution avec by

do.call(rbind, unname(by(df, df$f, function(x) x[x$v1 == min(x$v1),])))
##   f  v1 v2
## 1 a 1.3  1
## 3 b 2.0  3
## 6 c 1.1  6
## 8 d 3.1  8




dataframe