[英]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
其中f1
, f2
是用於旋轉的函數
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_wider
和unnest
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.