在数据帧列表上应用函数的有效方法
An efficient way to apply a function over a list of dataframes
我在 R 中有一个数据帧列表。我需要做的是对每个数据帧应用一个函数,在本例中删除特殊字符,并返回一个数据帧列表。
使用 lapply
和 as.data.frame
以下内容工作正常并提供了我所需要的:
my_df =data.frame(names = seq(1,10), chars = c("abcabc!!", "abcabc234234!!"))
my_list = list(my_df, my_df, my_df)
#str(my_list)
List of 3
$ :'data.frame': 10 obs. of 2 variables: ...
new_list <- lapply(my_list, function(y) as.data.frame(lapply(y, function(x) gsub("[^[:alnum:][:space:]']", "", x))))
# str(new_list)
List of 3
$ :'data.frame': 10 obs. of 2 variables:
..$ names: Factor w/ 10 levels "1","10","2","3",..: 1 3 4 5 6 7 8 9 10 2
..$ chars: Factor w/ 2 levels "abcabc","abcabc234234": 1 2 1 2 1 2 1 2 1 2
$ :'data.frame': 10 obs. of 2 variables:
..$ names: Factor w/ 10 levels "1","10","2","3",..: 1 3 4 5 6 7 8 9 10 2
..$ chars: Factor w/ 2 levels "abcabc","abcabc234234": 1 2 1 2 1 2 1 2 1 2
$ :'data.frame': 10 obs. of 2 variables:
..$ names: Factor w/ 10 levels "1","10","2","3",..: 1 3 4 5 6 7 8 9 10 2
..$ chars: Factor w/ 2 levels "abcabc","abcabc234234": 1 2 1 2 1 2 1 2 1 2
但我想知道是否有一种不需要嵌套的更有效的方法lapply
。也许是 returns 将元素作为数据框的不同应用系列函数?
我们不需要嵌套的 lapply
,只需一个带有 transform
的 lapply
即可
lapply(my_list, transform, chars = gsub("[^[:alnum:][:space:]']", "", chars))
模式可以压缩到"[^[[:alnum:] ']"
虽然@akrun 是正确的,你的第二个 lapply
调用在这个例子中是无用的,但我认为它不能解决许多列可能相关的一般情况,而且不知道哪个可能是相关的。
这里效率低下的是使用 as.data.frame
的转换,而不是内部 lapply
调用。 lapply
调用本身几乎与将函数应用于单个向量或相同大小的矩阵一样快。
如果你真的想在这里更省时,我建议使用data.table
。我把这个例子放大了一点,这样我们就可以计时了。
library(data.table)
f <- function(x) gsub("[^[:alnum:][:space:]']", "", x)
my_df <- as.data.frame(matrix(paste0(sample(c(letters,'!'), size=1000000, replace=T),
sample(c(letters,'!'), size=1000000, replace=T)),
ncol=250), stringsAsFactors = FALSE)
my_list = list(my_df, my_df, my_df)
system.time(lapply(my_list, function(y) as.data.frame(lapply(y, f))))
# 2.256 seconds
my_dt <- as.data.table(my_df)
my_list2 = list(my_dt, my_dt, my_dt)
system.time(lapply(my_list2, function(y) y[,lapply(.SD,f)]))
# 1.180 seconds
我在 R 中有一个数据帧列表。我需要做的是对每个数据帧应用一个函数,在本例中删除特殊字符,并返回一个数据帧列表。
使用 lapply
和 as.data.frame
以下内容工作正常并提供了我所需要的:
my_df =data.frame(names = seq(1,10), chars = c("abcabc!!", "abcabc234234!!"))
my_list = list(my_df, my_df, my_df)
#str(my_list)
List of 3
$ :'data.frame': 10 obs. of 2 variables: ...
new_list <- lapply(my_list, function(y) as.data.frame(lapply(y, function(x) gsub("[^[:alnum:][:space:]']", "", x))))
# str(new_list)
List of 3
$ :'data.frame': 10 obs. of 2 variables:
..$ names: Factor w/ 10 levels "1","10","2","3",..: 1 3 4 5 6 7 8 9 10 2
..$ chars: Factor w/ 2 levels "abcabc","abcabc234234": 1 2 1 2 1 2 1 2 1 2
$ :'data.frame': 10 obs. of 2 variables:
..$ names: Factor w/ 10 levels "1","10","2","3",..: 1 3 4 5 6 7 8 9 10 2
..$ chars: Factor w/ 2 levels "abcabc","abcabc234234": 1 2 1 2 1 2 1 2 1 2
$ :'data.frame': 10 obs. of 2 variables:
..$ names: Factor w/ 10 levels "1","10","2","3",..: 1 3 4 5 6 7 8 9 10 2
..$ chars: Factor w/ 2 levels "abcabc","abcabc234234": 1 2 1 2 1 2 1 2 1 2
但我想知道是否有一种不需要嵌套的更有效的方法lapply
。也许是 returns 将元素作为数据框的不同应用系列函数?
我们不需要嵌套的 lapply
,只需一个带有 transform
的 lapply
即可
lapply(my_list, transform, chars = gsub("[^[:alnum:][:space:]']", "", chars))
模式可以压缩到"[^[[:alnum:] ']"
虽然@akrun 是正确的,你的第二个 lapply
调用在这个例子中是无用的,但我认为它不能解决许多列可能相关的一般情况,而且不知道哪个可能是相关的。
这里效率低下的是使用 as.data.frame
的转换,而不是内部 lapply
调用。 lapply
调用本身几乎与将函数应用于单个向量或相同大小的矩阵一样快。
如果你真的想在这里更省时,我建议使用data.table
。我把这个例子放大了一点,这样我们就可以计时了。
library(data.table)
f <- function(x) gsub("[^[:alnum:][:space:]']", "", x)
my_df <- as.data.frame(matrix(paste0(sample(c(letters,'!'), size=1000000, replace=T),
sample(c(letters,'!'), size=1000000, replace=T)),
ncol=250), stringsAsFactors = FALSE)
my_list = list(my_df, my_df, my_df)
system.time(lapply(my_list, function(y) as.data.frame(lapply(y, f))))
# 2.256 seconds
my_dt <- as.data.table(my_df)
my_list2 = list(my_dt, my_dt, my_dt)
system.time(lapply(my_list2, function(y) y[,lapply(.SD,f)]))
# 1.180 seconds