在 R 中跨列应用用户定义的函数
Apply user defined function across columns in R
我在 R 中有两个函数可以将弧度和角度转换为笛卡尔坐标,如下所示:
x_cart<-function(theta,r){
return(r * cos (theta))
}
y_cart<-function(theta,r){
return(r * sin (theta))
}
然后我想应用此函数在我的数据框中从 angle
和 radius
列中创建两个新列作为 x
和 y
。当我使用 lapply 时,出现参数 r is missing with no default.
的错误
df$x<-apply(df[,c("angle_adj","hit_distance")],1, x_cart())
测试数据
angle<-c(10,15,20)
radius<-c(15,35,10)
df<-data.frame(angle,radius)
你不需要 apply
,使用这样的东西:
x_cart<-function(theta,r){
return(r * cos (theta))
}
y_cart<-function(theta,r){
return(r * sin (theta))
}
angle<-c(10,15,20)
radius<-c(15,35,10)
df<-data.frame(angle,radius)
df$x <- x_cart(df$angle, df$radius)
# or using with()
df$x <- with(df, x_cart(angle, radius))
或更紧凑:
cart <- function(theta,r){
r * c(cos(theta), sin(theta))
}
df <- data.frame(
angle = c(10, 15, 20),
radius = c(15, 35, 10)
)
df[c("x", "y")] <- cart(df$angle, df$radius)
已更新
感谢亲爱的@ThomasIsCoding 提供的输入,我们可以节省一行并使用 base R 的新原生管道:
sapply(c(x_cart,y_cart),function(f) mapply(f,df1$angle, df1$radius)) |>
data.frame() |>
cbind(df1) -> df2
colnames(df2) <- c("x", "y", "angle", "radius")
df2
x y angle radius
1 -12.586073 -8.160317 10 15
2 -26.589077 22.760074 15 35
3 4.080821 9.129453 20 10
您还可以将此与 tidyverse
一起使用,作为一种更加自动化流程的方式:
library(dplyr)
library(purrr)
# First wrap our arguments in a list
lst <- list(df1$angle, df1$radius)
# Then we create a character vector of our function names
c("x_cart", "y_cart") %>%
map(~ exec(.x, !!!lst)) %>%
set_names(nm = c("x", "y")) %>%
bind_cols() %>%
bind_cols(df)
# A tibble: 3 x 4
x y angle radius
<dbl> <dbl> <dbl> <dbl>
1 -12.6 -8.16 10 15
2 -26.6 22.8 15 35
3 4.08 9.13 20 10
用于 apply
用法的 base-R 解决方案。在这种情况下,最好重新定义您的函数:
x_cart_2 <- function(input) { return(input[2] * cos(input[1])) }
df$x <- apply(df[,c("angle","radius")],1, x_cart_2)
returns
angle radius x
1 10 15 -12.586073
2 15 35 -26.589077
3 20 10 4.080821
一个 tidyverse 选项。
library(dplyr)
df %>%
mutate(X = x_cart(angle, radius),
Y = y_cart(angle, radius))
# angle radius X Y
# 1 10 15 -12.586073 -8.160317
# 2 15 35 -26.589077 22.760074
# 3 20 10 4.080821 9.129453
像下面那样尝试 sapply
cbind(
df,
sapply(
setNames(c(x_cart, y_cart), c("x", "y")),
function(f) with(df, f(angle, radius))
)
)
这给出了
angle radius x y
1 10 15 -12.586073 -8.160317
2 15 35 -26.589077 22.760074
3 20 10 4.080821 9.129453
我在 R 中有两个函数可以将弧度和角度转换为笛卡尔坐标,如下所示:
x_cart<-function(theta,r){
return(r * cos (theta))
}
y_cart<-function(theta,r){
return(r * sin (theta))
}
然后我想应用此函数在我的数据框中从 angle
和 radius
列中创建两个新列作为 x
和 y
。当我使用 lapply 时,出现参数 r is missing with no default.
df$x<-apply(df[,c("angle_adj","hit_distance")],1, x_cart())
测试数据
angle<-c(10,15,20)
radius<-c(15,35,10)
df<-data.frame(angle,radius)
你不需要 apply
,使用这样的东西:
x_cart<-function(theta,r){
return(r * cos (theta))
}
y_cart<-function(theta,r){
return(r * sin (theta))
}
angle<-c(10,15,20)
radius<-c(15,35,10)
df<-data.frame(angle,radius)
df$x <- x_cart(df$angle, df$radius)
# or using with()
df$x <- with(df, x_cart(angle, radius))
或更紧凑:
cart <- function(theta,r){
r * c(cos(theta), sin(theta))
}
df <- data.frame(
angle = c(10, 15, 20),
radius = c(15, 35, 10)
)
df[c("x", "y")] <- cart(df$angle, df$radius)
已更新
感谢亲爱的@ThomasIsCoding 提供的输入,我们可以节省一行并使用 base R 的新原生管道:
sapply(c(x_cart,y_cart),function(f) mapply(f,df1$angle, df1$radius)) |>
data.frame() |>
cbind(df1) -> df2
colnames(df2) <- c("x", "y", "angle", "radius")
df2
x y angle radius
1 -12.586073 -8.160317 10 15
2 -26.589077 22.760074 15 35
3 4.080821 9.129453 20 10
您还可以将此与 tidyverse
一起使用,作为一种更加自动化流程的方式:
library(dplyr)
library(purrr)
# First wrap our arguments in a list
lst <- list(df1$angle, df1$radius)
# Then we create a character vector of our function names
c("x_cart", "y_cart") %>%
map(~ exec(.x, !!!lst)) %>%
set_names(nm = c("x", "y")) %>%
bind_cols() %>%
bind_cols(df)
# A tibble: 3 x 4
x y angle radius
<dbl> <dbl> <dbl> <dbl>
1 -12.6 -8.16 10 15
2 -26.6 22.8 15 35
3 4.08 9.13 20 10
用于 apply
用法的 base-R 解决方案。在这种情况下,最好重新定义您的函数:
x_cart_2 <- function(input) { return(input[2] * cos(input[1])) }
df$x <- apply(df[,c("angle","radius")],1, x_cart_2)
returns
angle radius x
1 10 15 -12.586073
2 15 35 -26.589077
3 20 10 4.080821
一个 tidyverse 选项。
library(dplyr)
df %>%
mutate(X = x_cart(angle, radius),
Y = y_cart(angle, radius))
# angle radius X Y
# 1 10 15 -12.586073 -8.160317
# 2 15 35 -26.589077 22.760074
# 3 20 10 4.080821 9.129453
像下面那样尝试 sapply
cbind(
df,
sapply(
setNames(c(x_cart, y_cart), c("x", "y")),
function(f) with(df, f(angle, radius))
)
)
这给出了
angle radius x y
1 10 15 -12.586073 -8.160317
2 15 35 -26.589077 22.760074
3 20 10 4.080821 9.129453