繁体   English   中英

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

[英]How to mutate multiple columns into new multiple columns with dplyr

我正在尝试将 3 列更改为更大表中的 3 个新列(具有更多列)。 3 个新列依赖于第一个现有的 3 个列。 第 4 个新列仅依赖于第 4 个现有列。 基本上,我想在 3D 空间中旋转点的坐标(在 x、y、z 列中)并存储在新列(x_rot、y_rot、z_rot)中。

我可以将 3 列变异为 1 列新列,并对每个维度重复此操作,这似乎很浪费。 如果我的自定义 function 将获得 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和 function旋转

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其中f1f2是用于旋转的函数

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

across devel版本中,使用mutate和 cross

df2 <- df1 %>%
           mutate(across(vars(x, y, z),  f1, names = "{col}_rot"), 
                   col4_rot = f2(col4))

更新

基于更新的function,我们可以使用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 

或者另一种选择是在summarise中返回list ,然后执行unnest_widerunnest

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)))
 }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM