如何使用dplyr将多列突变为新的多列

通过

我正在尝试将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_atwhere f1,这f2是用于旋转的函数

library(dplyr)
df2 <- df1 %>%
         mutate_at(vars(x, y, z),   list(rot =  f1)) %>%
         mutate(col4_rot = f2(col4))

devel版本中,mutateacross

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 

或另一个选择是返回listinsummarise然后执行unnest_widerandunnest

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] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章