我正在尝试将3列突变为一个更大的表(具有更多列)中的3个新列。新列中的3个依赖于第一个现有的3列。新的第4列仅取决于现有的第4列。基本上,我想在3D空间中旋转点的坐标(在x,y,z列中)并存储在新的列(x_rot,y_rot,z_rot)中。
我可以将3列突变为1个新列,并为每个维度重复此操作,这似乎很浪费。如果我的自定义函数将获得3个坐标并返回3个旋转坐标,则将更加简单。
在这里,如果我使用for循环执行此操作:
df = data.frame(x = rnorm(5), y = rnorm(5), z = rnorm(5))
for(i in nrow(df){
r = sqrt(df$x[i] ^ 2 + df$y[i] ^ 2 + df$z[i] ^ 2)
phi = atan2(y = df$y[i], x = df$x[i])
phi = phi + rotationAngle1
theta = acos(df$z[i] / r)
theta = theta + rotationAngle2
df$x_ROT[i] = r * cos(phi) * sin(theta)
df$y_ROT[i] = r * sin(phi) * sin(theta)
df$z_ROT[i] = r * cos(theta)
}
或使用mutate_at并旋转功能:
rotate = function(x,y,z){
r = sqrt(x ^ 2 + y ^ 2 + z ^ 2)
phi = atan2(y = y, x = x)
phi = phi + rotationAngle1
theta = acos(z / r)
theta = theta + rotationAngle2
return(c(r * cos(phi) * sin(theta), r * sin(phi) * sin(theta),r * cos(theta))
# OR
return(list(x = r * cos(phi) * sin(theta), y = r * sin(phi) * sin(theta), z = r * cos(theta))
}
如何使用dplyr做到这一点?我如何制定df%>%group_by(group)%>%mutate_at(???)
有了dplyr
,我们可以使用mutate_at
where f1
,这f2
是用于旋转的函数
library(dplyr)
df2 <- df1 %>%
mutate_at(vars(x, y, z), list(rot = f1)) %>%
mutate(col4_rot = f2(col4))
在devel
版本中,mutate
与across
df2 <- df1 %>%
mutate(across(vars(x, y, z), f1, names = "{col}_rot"),
col4_rot = f2(col4))
基于更新的功能,我们可以使用 pmap
library(purrr)
library(stringr)
pmap_dfr(df, rotate) %>%
rename_all(~ str_c(., '_rot')) %>%
bind_cols(df, .)
# A tibble: 5 x 6
# x y z x_rot y_rot z_rot
# <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#1 -0.303 1.20 -0.503 -0.0457 0.00799 -1.34
#2 -0.0662 -0.599 1.45 1.35 -0.793 0.0405
#3 0.239 0.953 1.49 -1.39 1.09 -0.288
#4 -0.490 0.0106 -0.622 0.157 0.333 -0.701
#5 0.554 1.08 0.761 -0.748 0.928 -0.802
哪里
rotationAngle2 <- 20
rotate <- function(x,y,z){
r = sqrt(x ^ 2 + y ^ 2 + z ^ 2)
phi = atan2(y = y, x = x)
phi = phi + rotationAngle2
theta = acos(z / r)
theta = theta + rotationAngle2
return(list(x = r * cos(phi) * sin(theta),
y = r * sin(phi) * sin(theta),
z = r * cos(theta)))
}
也可以 mutate
library(tidyr)
df %>%
rowwise %>%
mutate(out = list(rotate(x, y, z))) %>%
unnest_wider(c(out))
# A tibble: 5 x 6
# x y z x_rot y_rot z_rot
# <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#1 -0.303 1.20 -0.503 -0.0457 0.00799 -1.34
#2 -0.0662 -0.599 1.45 1.35 -0.793 0.0405
#3 0.239 0.953 1.49 -1.39 1.09 -0.288
#4 -0.490 0.0106 -0.622 0.157 0.333 -0.701
#5 0.554 1.08 0.761 -0.748 0.928 -0.802
或另一个选择是返回list
insummarise
然后执行unnest_wider
andunnest
df %>%
summarise(out = list(rotate(x, y, z))) %>%
unnest_wider(c(out)) %>%
unnest(cols = everything()) %>%
bind_cols(df, .)
# A tibble: 5 x 6
# x y z x_rot y_rot z_rot
# <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#1 -0.303 1.20 -0.503 -0.0457 0.00799 -1.34
#2 -0.0662 -0.599 1.45 1.35 -0.793 0.0405
#3 0.239 0.953 1.49 -1.39 1.09 -0.288
#4 -0.490 0.0106 -0.622 0.157 0.333 -0.701
#5 0.554 1.08 0.761 -0.748 0.928 -0.802
哪里
rotate <- function(x,y,z){
r = sqrt(x ^ 2 + y ^ 2 + z ^ 2)
phi = atan2(y = y, x = x)
phi = phi + rotationAngle2
theta = acos(z / r)
theta = theta + rotationAngle2
return(list(x_rot = r * cos(phi) * sin(theta),
y_rot = r * sin(phi) * sin(theta),
z_rot = r * cos(theta)))
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句