提问人:twilightecologist 提问时间:11/16/2023 最后编辑:halfertwilightecologist 更新时间:11/17/2023 访问量:71
如何实现在 R 中的数据帧列表上调用特定列名的函数?lapply 错误
How do I implement a function that calls specific column names on a list of data frames in R? Error with lapply
问:
我对 R 很陌生。我想使用一个执行多个计算的函数,这些计算在数据框中的列之间进行计算,并创建保存最终计算的新列。我想在数据帧列表中实现此函数,但是,当我尝试使用 lapply 时,我收到一个错误,指出缺少第一列名称且没有默认值。
我知道这一定是我格式化函数的问题,但是我正在努力为此想出解决方案。我该如何进行?
#create example data frames, my real data frames are named similarly, with an identical names and a unique id (i.e. example_df_uniqueidnumber), each data frame has columns named identically
df1 <- data.frame(pt1_X = c(1,2,3), pt2_X = c(1,2,3), pt1_Y = c(1,2,3), pt2_Y =c(1,2,3))
df2 <- data.frame(pt1_X = c(1,2,3), pt2_X = c(1,2,3), pt1_Y = c(1,2,3), pt2_Y =c(1,2,3))
#create my example function
#NOTE: I call the data "data" (instead of df1 or df2), because I am unsure of what to use instead, as each file name is different due to the unique identifier
calculate_angles1 <- function(data, pt1_X, pt1_Y, pt2_X, pt2_Y) {
data$Mx <- (data[[pt1_X]] - data[[pt2_X]])
data$My <- (data[[pt1_Y]] - data[[pt2_Y]])
return(data)
}
#create my list of data frames
new_list <- list(df1, df2)
#use lapply to attempt to apply my function to my list of data frames
AoA <- lapply(new_list, calculate_angles1)
运行lapply函数后,收到此错误消息。
Error in (function(x, i, exact) if (is.matrix(i)) as.matrix(x)[[i]] else .subset2(x, :
argument "pt1_X" is missing, with no default
答:
请尝试以下代码
library(dplyr)
library(purrr)
new_list <- list(df1, df2)
map(new_list, \(x) {
x <- x %>% mutate(mx=pt1_X-pt2_X, my=pt1_Y-pt2_Y)
return(x)
})
[[1]]
pt1_X pt2_X pt1_Y pt2_Y mx my
1 1 1 1 1 0 0
2 2 2 2 2 0 0
3 3 3 3 3 0 0
[[2]]
pt1_X pt2_X pt1_Y pt2_Y mx my
1 1 1 1 1 0 0
2 2 2 2 2 0 0
3 3 3 3 3 0 0
要使用 ,您需要将列名引起来:calculate_angles2
calculate_angles2(df1, 'pt1_X', 'pt2_X', 'pt1_Y', 'pt2_Y')
或者,如果您坚持使用不带引号的名称,则可以在 base R 中执行此操作:
calculate_angles3 <- function(data, a, b, c, d){
data$Mx <- eval(substitute(a-b), data)
data$My <- eval(substitute(c-d), data)
data
}
calculate_angles3(df1, pt1_X, pt2_X, pt1_Y, pt2_Y)
(或使用 {rlang} 提供的附加功能进行非标准评估)
从这里开始:
calculate_angles1 <- function(data) {
Mx <- data[, "pt1_X"] - data[, "pt2_X"]
My <- data[, "pt1_Y"] - data[, "pt2_Y"]
do.call("cbind", list(data, "Mx" = Mx, "My" = My))
}
lapply(new_list, calculate_angles1)
您定义了函数以包含一堆未提供且未定义默认值的其他参数。您只需更改功能即可使事情变得更容易。lapply
calculate_angles1
calculate_angles1 <- function(data) {
data$Mx <- (data$pt1_X - data$pt2_X)
data$My <- (data$pt1_Y - data$pt2_Y)
return(data)
}
调用 时,R 会查找名为 的变量以获取列信息。如果你这样做了并运行了,你会看到你得到的是“pt2_Y”列,而不是“pt1_X”。这与从 data.frame 中提取列不同。data[[pt1_X]]
pt1_X
pt1_X <- "pt2_Y"
df1[[pt1_X]]
data$pt1_X
pt1_X
函数的问题在于名称必须用双引号括起来。此外,要处理变量值,请使用 single 而不是 double 。
因此,该函数可以重写为:[
[[
calculate_angles1 <- function(data) {
data["Mx"] <- data["pt1_X"] - data["pt2_X"]
data["My"] <- data["pt1_Y"] - data["pt2_Y"]
data.frame(data)
}
要将您的函数应用于数据帧列表,有多种方法,如您所述:lapply
lapply
new_list <- lapply(new_list, calculate_angles1)
或者使用包或系列中的功能,我认为这会更直接。就像您的函数一样,它以数据帧作为第一个参数并返回数据帧。因此,您可以像我在这里所做的那样调用动词来操作内部的数据,即调用 from 来创建新变量。map()
purrr
tidyverse
Data frame function
dplyr
map
mutate()
dplyr
地图
library(tidyverse)
new_list <- map(new_list, ~ mutate(.x, Mx=pt1_X-pt2_X, My=pt1_Y-pt2_Y))
这两个选项都会产生相同的输出:
> new_list
[[1]]
pt1_X pt2_X pt1_Y pt2_Y Mx My
1 1 1 1 1 0 0
2 2 2 2 2 0 0
3 3 3 3 3 0 0
[[2]]
pt1_X pt2_X pt1_Y pt2_Y Mx My
1 1 1 1 1 0 0
2 2 2 2 2 0 0
3 3 3 3 3 0 0
评论
上一个:调用内联函数时未定义引用
评论