我想将以下功能应用于数据框的列:
ff <- function(w, epsi, df) {
res <- w*(max(df, na.rm = T) - min(df, na.rm=T)+2*epsi)+min(df, na.rm = T) - epsi
return(res)
}
应使用参数w
和epsi
将函数应用于df
的每一列。该函数必须取w
的每个值,然后乘以df
对应列的最大值减去df
对应列的最小值,依此类推。
例如:
> w
# A tibble: 5 x 2
A B
<dbl> <dbl>
1 0.290 0.928
2 0.917 0.929
3 0.910 0.919
4 0.243 0.908
5 0.936 0.901
和df
是:
> df
# A tibble: 10 x 2
A B
<dbl> <dbl>
1 0.977 1.03
2 1.04 1.15
3 0.929 0.875
4 1.12 1.15
5 0.913 1.05
6 1.00 1.09
7 0.972 1.03
8 0.919 1.04
9 0.935 0.973
10 1.08 1.17
因此对于w
的第一个元素0.290,该函数将0.290乘以df
列中的A
的最大值(1.12),依此类推。
如何将dplyr
应用于w
?
我尝试过:
w_new = w %>% mutate_each(ff(w,0.001, df))
但它不是一次只接受一列,而是尝试一次对所有列进行操作。
答案 0 :(得分:2)
OP表示希望使用基于dplyr
的解决方案来解决此问题,因此我想使用dplyr
提供一个答案。
在这种情况下,我们需要在另一个表中查找对应的列(名称),那么最好不要依赖列的顺序,而要使用特定的列名称。使用quo_name
和quo
函数可以访问dplyr::mutate_all
函数范围内的列名。
使用dplyr::mutate_all
的解决方案可以是:
# Re-wirte fucntion to accept the column name for df
ff <- function(x, epsi, colName) {
res <- x*(max(df[,colName], na.rm = TRUE) - min(df[,colName], na.rm=TRUE) +
2*epsi)+min(df[,colName], na.rm = TRUE) - epsi
return(res)
}
library(dplyr)
# The corresponding column names is passed to ff using quo_name(quo(.))
w %>% mutate_all(funs(ff(., 0.001, quo_name(quo(.)) )))
# A B
# 1 0.972610 1.149616
# 2 1.103653 1.149913
# 3 1.102190 1.146943
# 4 0.962787 1.143676
# 5 1.107624 1.141597
数据:
w <- read.table(text =
"A B
1 0.290 0.928
2 0.917 0.929
3 0.910 0.919
4 0.243 0.908
5 0.936 0.901",
header = TRUE)
df <- read.table(text =
"A B
1 0.977 1.03
2 1.04 1.15
3 0.929 0.875
4 1.12 1.15
5 0.913 1.05
6 1.00 1.09
7 0.972 1.03
8 0.919 1.04
9 0.935 0.973
10 1.08 1.17",
header = TRUE)
答案 1 :(得分:1)
这是使用mapply
mapply(
function(x, y, epsi = 0.001)
x * (max(y, na.rm = T) - min(y, na.rm = T) + 2 * epsi) + min(y, na.rm = T) - epsi,
w, df)
# A B
#[1,] 0.972610 1.149616
#[2,] 1.103653 1.149913
#[3,] 1.102190 1.146943
#[4,] 0.962787 1.143676
#[5,] 1.107624 1.141597
说明:mapply
逐列将功能应用于w
和df
,并将结果简化为5x2 matrix
。
稍微重新定义ff
,这可以写得更简洁
ff <- function(x, y, epsi = 0.001)
x * (max(y, na.rm = T) - min(y, na.rm = T) + 2 * epsi) + min(y, na.rm = T) - epsi
mapply(ff, w, df)
或使用purrr::map2_df
作为
w %>% map2_df(df, ff)
## A tibble: 5 x 2
# A B
# <dbl> <dbl>
#1 0.973 1.15
#2 1.10 1.15
#3 1.10 1.15
#4 0.963 1.14
#5 1.11 1.14
对microbenchmark
和mutate_all
方法进行非常快速,肮脏的map2
分析的结果看起来像这样:
res <- microbenchmark(
map2 = {
ff <- function(x, y, epsi = 0.001)
x * (max(y, na.rm = T) - min(y, na.rm = T) + 2 * epsi) + min(y, na.rm = T) - epsi
w %>% map2_df(df, ff)
},
mutate_all = {
ff <- function(x, epsi, colName) {
res <- x*(max(df[,colName], na.rm = TRUE) - min(df[,colName], na.rm=TRUE) +
2*epsi)+min(df[,colName], na.rm = TRUE) - epsi
return(res)
}
w %>% mutate_all(funs(ff(., 0.001, quo_name(quo(.)) )))
}
)
res
#Unit: microseconds
# expr min lq mean median uq max neval
# map2 320.537 371.1365 495.7786 397.6755 449.4445 8599.661 100
# mutate_all 1916.788 1998.2105 2312.5878 2059.7650 2290.1415 11169.320 100
library(ggplot2)
autoplot(res)