Reputation: 1044
I want to mutate column content of a data frame so that the cell content is prefixed by the column name:
> x <- data.frame(VarX = rep(c("A","B"),2), VarY = rep(c("C","D"),2))
> x
VarX VarY
1 A C
2 B D
3 A C
4 B D
> x$VarX <- paste0("VarX", x$VarX)
> x$VarY <- paste0("VarY", x$VarY)
> x
VarX VarY
1 VarXA VarYC
2 VarXB VarYD
3 VarXA VarYC
4 VarXB VarYD
but in generic. The closes furthest I got is by:
x <- data.frame(VarX = rep(c("A","B"),2), VarY = rep(c("C","D"),2))
columns = c("VarX", "VarY")
for(col in columns)
{
x <- x %>% mutate_at( .vars = col, ~paste0(col, .) )
}
x
but i do not like the for loop. Can anyone improve the code?
Please also note the code to work on column selection of x.
x <- data.frame(VarX = rep(c("A","B"),2), VarY = rep(c("C","D"),2),
num = 1:4)
and I only want to modify the column VarX and VarY.
Upvotes: 3
Views: 1022
Reputation: 887118
We can use imap
, which would also include the column names of each column if we need to extract. Here, we paste
the column names (.y
) with the column values (.x
)
library(tidyverse)
imap(x, ~ paste0(.y, .x)) %>%
bind_cols
# A tibble: 4 x 2
# VarX VarY
# <chr> <chr>
#1 VarXA VarYC
#2 VarXB VarYD
#3 VarXA VarYC
#4 VarXB VarYD
EDIT: Based on comments from @Moody_Mudskipper
imap_dfc(x, ~ paste0(.y, .x))
Or using base R
, we paste
the replicated column names of 'x' with matrix
of 'x' and assign it to the initial data.frame
x[] <- paste0(rep(colnames(x), each = nrow(x)), as.matrix(x))
x
# VarX VarY
#1 VarXA VarYC
#2 VarXB VarYD
#3 VarXA VarYC
#4 VarXB VarYD
Upvotes: 2
Reputation: 5281
In base r
data.frame(matrix(paste0(sort(rep(names(x),4L)), unlist(x)), ncol = 2))
Upvotes: 0
Reputation: 388982
We can use lapply
x[] <- lapply(seq_along(x), function(i) paste0(names(x)[i], x[,i]))
x
# VarX VarY
#1 VarXA VarYC
#2 VarXB VarYD
#3 VarXA VarYC
#4 VarXB VarYD
You can use appropriate sep
argument in paste0
to make it look clean.
If you have more number of columns and you want to select only some of them you can do
cols <- c("VarX","VarY")
x[cols] <- lapply(seq_along(x[cols]), function(i) paste0(names(x)[i], x[,i]))
x
# VarX VarY num
#1 VarXA VarYC 1
#2 VarXB VarYD 2
#3 VarXA VarYC 3
#4 VarXB VarYD 4
Upvotes: 1
Reputation: 8364
A solution with purrr
:
purrr::map2_dfc(colnames(x), x, paste0)
# A tibble: 4 x 2
V1 V2
<chr> <chr>
1 VarXA VarYC
2 VarXB VarYD
3 VarXA VarYC
4 VarXB VarYD
If you have more columns this works also, just subset by the ones that you need to change:
cols <- c("VarX", "VarY")
x[, cols] <- purrr::map2_dfc(cols, x[,cols], paste0)
x
# VarX VarY VarZ
# 1 VarXA VarYC E
# 2 VarXB VarYD F
# 3 VarXA VarYC E
# 4 VarXB VarYD F
Data:
x <- data.frame(VarX = rep(c("A","B"),2),
VarY = rep(c("C","D"),2),
VarZ = rep(c("E","F"),2))
Upvotes: 0
Reputation: 51592
You can try mapply
, i.e.
x[] <- mapply(paste0, names(x), x)
which gives,
VarX VarY 1 VarXA VarYC 2 VarXB VarYD 3 VarXA VarYC 4 VarXB VarYD
Upvotes: 2