witek
witek

Reputation: 1044

Prefix/suffix column content with column names

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

Answers (5)

akrun
akrun

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

niko
niko

Reputation: 5281

In base r

data.frame(matrix(paste0(sort(rep(names(x),4L)), unlist(x)), ncol = 2))

Upvotes: 0

Ronak Shah
Ronak Shah

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

RLave
RLave

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

Sotos
Sotos

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

Related Questions