/ / dplyr filter: Získajte riadky s minimálnou premennou, ale iba prvé, ak viacnásobné minimum - r, dplyr

filter dplyr: Získajte riadky s minimálnou premennou, ale iba prvé, ak je viacero minimá - r, dplyr

Chcem vytvoriť zoskupený filter pomocou dplyr, tak, že v každej skupine sa vráti len ten riadok, ktorý má minimálnu hodnotu premennej x.

Môj problém je: Ako sa očakávalo, v prípade viacerých minimá všetko sa vrátia riadky s minimálnou hodnotou. Ale v mojom prípade, Chcem len prvý riadok ak sú prítomné viaceré minimá.

Tu je príklad:

df <- data.frame(
A=c("A", "A", "A", "B", "B", "B", "C", "C", "C"),
x=c(1, 1, 2, 2, 3, 4, 5, 5, 5),
y=rnorm(9)
)

library(dplyr)
df.g <- group_by(df, A)
filter(df.g, x == min(x))

Podľa očakávaní sa vrátia všetky minimá:

Source: local data frame [6 x 3]
Groups: A

A x           y
1 A 1 -1.04584335
2 A 1  0.97949399
3 B 2  0.79600971
4 C 5 -0.08655151
5 C 5  0.16649962
6 C 5 -0.05948012

S ddply, tak by som sa k tejto úlohe blížil takto:

library(plyr)
ddply(df, .(A), function(z) {
z[z$x == min(z$x), ][1, ]
})

... ktorý funguje:

  A x           y
1 A 1 -1.04584335
2 B 2  0.79600971
3 C 5 -0.08655151

Otázka: Existuje spôsob, ako sa k tomu dostať v dplyre? (Z dôvodov rýchlosti)

odpovede:

66 pre odpoveď č. 1

aktualizovať

Pri dplyr> = 0,3 môžete použiť slice funkcia v kombinácii s which.min, čo by bol môj obľúbený prístup k tejto úlohe:

df %>% group_by(A) %>% slice(which.min(x))
#Source: local data frame [3 x 3]
#Groups: A
#
#  A x          y
#1 A 1  0.2979772
#2 B 2 -1.1265265
#3 C 5 -1.1952004

Pôvodná odpoveď

Pre vzorové dáta je možné použiť aj dve filter po sebe navzájom:

group_by(df, A) %>%
filter(x == min(x)) %>%
filter(1:n() == 1)

27 pre odpoveď č. 2

Len pre úplnosť: Tu je finále dplyr riešenie, odvodené z pripomienok @hadley a @Arun:

library(dplyr)
df.g <- group_by(df, A)
filter(df.g, rank(x, ties.method="first")==1)

14 pre odpoveď č. 3

Prečo stojí za to, tu je a data.table riešenie pre tých, ktorí môžu mať záujem:

# approach with setting keys
dt <- as.data.table(df)
setkey(dt, A,x)
dt[J(unique(A)), mult="first"]

# without using keys
dt <- as.data.table(df)
dt[dt[, .I[which.min(x)], by=A]$V1]

2 pre odpoveď № 4

To sa dá dosiahnuť použitím row_number skombinované s group_by. row_number spracováva väzby priradením poradia nielen hodnotou, ale aj relatívnym poradím v rámci vektora. Ak chcete získať prvý riadok každej skupiny s minimálnou hodnotou x:

df.g <- group_by(df, A)
filter(df.g, row_number(x) == 1)

Viac informácií nájdete v dplyr vinety na oknách.


0 pre odpoveď č. 5

Mám rád sqldf pre svoju jednoduchosť ..

sqldf("select A,min(X),y from "df.g" group by A")

Výkon:

A min(X)          y

1 A      1 -1.4836989

2 B      2  0.3755771

3 C      5  0.9284441

0 pre odpoveď č. 6

Iný spôsob, ako to urobiť:

set.seed(1)
x <- data.frame(a = rep(1:2, each = 10), b = rnorm(20))
x <- dplyr::arrange(x, a, b)
dplyr::filter(x, !duplicated(a))

výsledok:

  a          b
1 1 -0.8356286
2 2 -2.2146999

Mohlo by sa tiež ľahko prispôsobiť tak, aby sa v každej skupine získala maximálna hodnota.