dplyr过滤器功能源代码,当我单击filter()时,我无法获得, 源代码是UseMethod(),当我进行调试时。什么都没出现;
我的测试代码:
filter(irirs,Sepal.Length> 7.1)
所以我尝试编写自己的函数
第一版:
filter<-function(data,condition){
attach(data)
r<- data[which(condition,)]
detach(data)
return (r)
}
当我使用system.time()来比较dplyr:filter和mine:filter时,它很有效,比dplyr花费更多的时间;
第二版:
filter<-function(data,condition){
r<-with(data,data[which(condition),])
return (r)
}
它报告错误,找不到Sepal.Length。
我知道条件参数问题,
如果我直接使用with(irirs,irirs [which(Sepal.Length> 7.1),]),它可以工作,但是我需要一个自己的过滤器功能
我有两个问题:
非常感谢!
答案 0 :(得分:5)
有一些可能性:
myfilter1 <- function(data, condition) {
do.call(subset, list(data, substitute(condition)), envir = parent.frame())
}
myfilter1(iris, Sepal.Length > 7.1)
myfilter2 <- function(data, condition) {
eval.parent(substitute(with(data, data[condition, ])))
}
myfilter2(iris, Sepal.Length > 7.1)
library(gtools)
myfilter3 <- defmacro(data, condition, expr = {
with(data, data[condition, ])
})
myfilter3(iris, Sepal.Length > 7.1)
要阅读S3泛型f
的方法的源R代码,请首先列出方法:
methods(f)
,然后如果f.x
是列出的方法之一,请在R中输入不带括号的名称:
f.x
还是不起作用(在methods
输出中的名称后面有*的情况就是这种情况)
getAnywhere("f.x")
如果代码在CRAN上的程序包p中,那么我们可以在 cran p 中进行谷歌搜索,然后从程序包的CRAN主页下载其源代码,或者在github上通过搜索 cran github p来找到它。 并查看github网站上的源代码。
关于性能,这是我在PC上获得的:
library(dplyr)
library(gtools)
library(microbenchmark)
f1 <- function() {
len <- 7.1
myfilter1(iris, Sepal.Length > len)
}
f2 <- function() {
len <- 7.1
myfilter2(iris, Sepal.Length > len)
}
f3 <- function() {
len <- 7.1
myfilter3(iris, Sepal.Length > len)
}
fd <- function() {
len <- 7.1
filter(iris, Sepal.Length > len)
}
microbenchmark(f1(), f2(), f3(), fd())
给出以下内容。
Unit: microseconds
expr min lq mean median uq max neval cld
f1() 399.2 433.70 497.133 482.00 518.85 1362.6 100 b
f2() 301.4 326.15 374.078 364.50 407.65 579.1 100 a
f3() 302.4 330.65 375.650 352.25 397.15 623.0 100 a
fd() 1791.5 1948.60 2166.466 2117.35 2262.65 3443.7 100 c
myfilter2
和myfilter3
的平均时间大约相同,并且都快于其他两个。
答案 1 :(得分:1)
一种方法是在eval
中使用parse
text
,subset
来编写自己的filter
方法
my_filter <- function(data, condition) {
subset(data, eval(parse(text = condition)))
}
my_filter(iris, "Sepal.Length > 7.1")
# Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#106 7.6 3.0 6.6 2.1 virginica
#108 7.3 2.9 6.3 1.8 virginica
#110 7.2 3.6 6.1 2.5 virginica
#118 7.7 3.8 6.7 2.2 virginica
#119 7.7 2.6 6.9 2.3 virginica
#123 7.7 2.8 6.7 2.0 virginica
#126 7.2 3.2 6.0 1.8 virginica
#130 7.2 3.0 5.8 1.6 virginica
#131 7.4 2.8 6.1 1.9 virginica
#132 7.9 3.8 6.4 2.0 virginica
#136 7.7 3.0 6.1 2.3 virginica
my_filter(mtcars, "cyl == 6")
# mpg cyl disp hp drat wt qsec vs am gear carb
#Mazda RX4 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4
#Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4
#Hornet 4 Drive 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1
#Valiant 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1
#Merc 280 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4
#Merc 280C 17.8 6 167.6 123 3.92 3.440 18.90 1 0 4 4
#Ferrari Dino 19.7 6 145.0 175 3.62 2.770 15.50 0 1 5 6
关于您的第二个问题,请在此处回答:
答案 2 :(得分:0)
@G表示感谢。格洛腾迪克答案,
我比较了我的版本1过滤器,以及@G. Grothendieck
的{{1}}和myfilter2
和dplyr :: filter,
我使用system.time()进行比较,我的版本1效率最低,而“ myfilter2”最好,
每个函数执行myfilter1
次,使用10000
这是时间花费表:
func(irirs,Sepal.Length>7.1)
time_spend是system.time()的时间
我没有测试myfilter3是因为我只想使用基本包来实现我的目标
答案 3 :(得分:0)
我们可以使用const A1 = ["text", "test"]
const A2 = ["onetest", "two", "threetext", "fourtext"]
// I need to get the result as ["onetest", "threetext", "fourtext"]
console.log(A2.filter(r => r !== null && A1.some(s => r.indexOf(s) > -1)))
选项
tidyverse
或者,如果我们要传递不带引号的表达式,请使用library(dplyr)
my_filter <- function(data, condition) {
data %>%
filter(!! rlang::parse_expr(condition))
}
my_filter(mtcars, "cyl == 6")
# mpg cyl disp hp drat wt qsec vs am gear carb
#1 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4
#2 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4
#3 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1
#4 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1
#5 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4
#6 17.8 6 167.6 123 3.92 3.440 18.90 1 0 4 4
#7 19.7 6 145.0 175 3.62 2.770 15.50 0 1 5 6
enexpr