Reputation: 1000
I have a dataframe that looks like the following, but with more columns and rows.
dog_c cat_c cheese_c hat_c
3 4 3 2
3 1 2 5
5 2 1 4
I would like to create a dataframe that looks like the following. I want to square all the values in a given column from the original dataframe and then create a column name that's the same as the original but with a 2 on the end. I would then like to attach it to the original dataframe.
dog_c cat_c cheese_c hat_c dog_c2 cat_c2 cheese_c2 hat_c2
3 4 3 2 9 16 9 4
3 1 2 5 9 1 2 5
5 2 1 4 25 4 1 16
I know I could do this in the following way for each new column.
df$dog_c2 <- (df$dog_c)^2
Does anyone have suggestions for how I can do this more efficiently?
Upvotes: 1
Views: 40
Reputation: 886938
We can use mutate
with across
in the devel version of dplyr
library(dplyr)
df1 %>%
mutate(across(everything(), list(~ .x^2), names = "{col}2"))
# dog_c cat_c cheese_c hat_c dog_c2 cat_c2 cheese_c2 hat_c2
#1 3 4 3 2 9 16 9 4
#2 3 1 2 5 9 1 4 25
#3 5 2 1 4 25 4 1 16
Or for selected columns
nm1 <- c('dog_c','cat_c')
df1 %>%
mutate(across(all_of(nm1), list(~ .x^2), names = "{col}2"))
# dog_c cat_c cheese_c hat_c dog_c2 cat_c2
#1 3 4 3 2 9 16
#2 3 1 2 5 9 1
#3 5 2 1 4 25 4
Or with data.table
library(data.table)
setDT(df1)[, paste0(nm1, 2) := .SD^2, .SDcols = nm1]
df1 <- structure(list(dog_c = c(3L, 3L, 5L), cat_c = c(4L, 1L, 2L),
cheese_c = 3:1, hat_c = c(2L, 5L, 4L)), class = "data.frame",
row.names = c(NA, -3L))
Upvotes: 1
Reputation: 388807
You could do the same directly for dataframe as well :
df[paste0(names(df), 2)] <- df^2
df
# dog_c cat_c cheese_c hat_c dog_c2 cat_c2 cheese_c2 hat_c2
#1 3 4 3 2 9 16 9 4
#2 3 1 2 5 9 1 4 25
#3 5 2 1 4 25 4 1 16
If you want to do this in dplyr
, you can use mutate_all
library(dplyr)
df %>% mutate_all(list(`2` = ~. ^2))
If we want to do this only for selected columns, we can do :
cols <- c('dog_c','cat_c') #Use regex if there are lot of columns.
df[paste0(cols, 2)] <- df[cols]^2
# dog_c cat_c cheese_c hat_c dog_c2 cat_c2
#1 3 4 3 2 9 16
#2 3 1 2 5 9 1
#3 5 2 1 4 25 4
Or use mutate_at
with dplyr
df %>% mutate_at(cols, list(`2` = ~.^2))
data
df <- structure(list(dog_c = c(3L, 3L, 5L), cat_c = c(4L, 1L, 2L),
cheese_c = 3:1, hat_c = c(2L, 5L, 4L)), class = "data.frame",
row.names = c(NA, -3L))
Upvotes: 2