Chcel by som filtrovať riadky, kde aspoň jeden stĺpec, okrem P je väčší ako P, pomocou dplyr. Snažím sa nájsť riešenie filtrované vo všetkých stĺpcoch.
príklad
library(dplyr)
df <- tibble(P = c(2,4,5,6,1.4), B =
c(2.1,3,5.5,1.2, 2),
C = c(2.2, 3.8, 5.7, 5,
1.5))
Požadovaný výstup
df <- filter(df, B > P | C > P)
df
Jedno riešenie s použitím platí, čo by som sa chcel vyhnúť, ak je to možné:
filter(df, apply(df, 1, function(x) sum(x > x[1]) > 1))
odpovede:
2 pre odpoveď č. 1bez dplyr
...
df2 <- df[df$P!=apply(df,1,max),]
alebo s dplyr
...
df3 <- df %>% filter(P!=apply(df,1,max))
2 pre odpoveď č. 2
Tu je možnosť používať tidyverse
kde využívame map
a reduce
funkcie od purrr
získať logiku vector
na extract
(od magrittr
) riadky pôvodnej množiny údajov
library(tidyverse)
library(magrittr)
df %>%
select(-one_of("P")) %>%
map(~ .> df$P) %>%
reduce(`|`) %>%
extract(df, .,)
# A tibble: 3 × 3
# P B C
# <dbl> <dbl> <dbl>
#1 2.0 2.1 2.2
#2 5.0 5.5 5.7
#3 1.4 2.0 1.5
Toto je možné previesť aj na funkciu pomocou vývojovej verzie programu dplyr
(čoskoro bude prepustený 0.6.0
), ktorý zaviedol quosures
a unquote
na hodnotenie. enquo
je takmer podobná substitute
z base R
ktorý prijíma používateľský vstup a konvertuje ho quosure
, one_of
berie reťazcové argumenty, takže môže byť konvertovaný na reťazec s quo_name
funFilter <- function(dat, colToCompare){
colToCompare <- quo_name(enquo(colToCompare))
dat %>%
select(-one_of(colToCompare)) %>%
map(~ .> dat[[colToCompare]]) %>%
reduce(`|`) %>%
extract(dat, ., )
}
funFilter(df, P)#compare all other columns with P
# A tibble: 3 × 3
# P B C
# <dbl> <dbl> <dbl>
#1 2.0 2.1 2.2
#2 5.0 5.5 5.7
#3 1.4 2.0 1.5
funFilter(df, B) #compare all other columns with B
# A tibble: 4 × 3
# P B C
# <dbl> <dbl> <dbl>
#1 2 2.1 2.2
#2 4 3.0 3.8
#3 5 5.5 5.7
#4 6 1.2 5.0
Tento výraz môžeme tiež analyzovať
v1 <- setdiff(names(df), "P")
filter(df, !!rlang::parse_quosure(paste(v1, "P", sep=" > ", collapse=" | ")))
# A tibble: 3 × 3
# P B C
# <dbl> <dbl> <dbl>
#1 2.0 2.1 2.2
#2 5.0 5.5 5.7
#3 1.4 2.0 1.5
Môže sa to stať aj funkciou
funFilter2 <- function(dat, colToCompare){
colToCompare <- quo_name(enquo(colToCompare))
v1 <- setdiff(names(dat), colToCompare)
expr <- rlang::parse_quosure(paste(v1, colToCompare, sep= " > ", collapse= " | "))
dat %>%
filter(!!expr)
}
funFilter2(df, P)
# A tibble: 3 × 3
# P B C
# <dbl> <dbl> <dbl>
#1 2.0 2.1 2.2
#2 5.0 5.5 5.7
#3 1.4 2.0 1.5
funFilter2(df, B)
# A tibble: 4 × 3
# P B C
# <dbl> <dbl> <dbl>
#1 2 2.1 2.2
#2 4 3.0 3.8
#3 5 5.5 5.7
#4 6 1.2 5.0
Môže to byť iný prístup pmax
df %>%
filter(do.call(pmax, .) > P)
# A tibble: 3 × 3
# P B C
# <dbl> <dbl> <dbl>
#1 2.0 2.1 2.2
#2 5.0 5.5 5.7
#3 1.4 2.0 1.5