mojek
mojek

Reputation: 307

Paste data frame without changing into factor levels

I have vectors let say a,b,c,d as below:

 a <- c(1,2,3,4)
 b <- c("L","L","F","L")
 c <- c(11,22,33,44)
 d <- c("Y", "N", "Y","Y")

And I try to use paste to get this output (1):

paste(a,b,c,d, sep = "$", collapse = "%")
[1] "1$L$11$Y%2$L$22$N%3$F$33$Y%4$L$44$Y"

Then I change it into this, let say df:

df <- data.frame(a,b,c,d)

and get this output (2):

paste(df, sep = "$", collapse = "%")
[1] "c(1, 2, 3, 4)%c(2, 2, 1, 2)%c(11, 22, 33, 44)%c(2, 1, 2, 2)"

My question is: (1) Can somebody explain to me why in df it change its elements into numeric? (2) Is there any other way that I can use df to get output (1)?

Upvotes: 3

Views: 448

Answers (4)

andrew_reece
andrew_reece

Reputation: 21274

Here's a dplyr approach:

pull(summarise(unite(df, tmp, 1:ncol(df), sep="$"), paste(tmp, collapse="%")))

Or:

df %>%
  unite(tmp, 1:ncol(df),sep="$") %>%
  summarise(output = paste(tmp, collapse="%")) %>%
  pull()

Upvotes: 0

Rich Scriven
Rich Scriven

Reputation: 99331

paste runs as.character (or something similar internally) on its ... arguments, effectively deparsing the list. Have a look at

as.character(df)
# [1] "c(1, 2, 3, 4)"     "c(2, 2, 1, 2)"     "c(11, 22, 33, 44)" "c(2, 1, 2, 2)"    
deparse(df$a)
# [1] "c(1, 2, 3, 4)"

Your code is pasting these values together. To get around this, you can use do.call.

do.call(paste, c(df, sep = "$", collapse = "%"))
# [1] "1$L$11$Y%2$L$22$N%3$F$33$Y%4$L$44$Y"

Upvotes: 4

Ronak Shah
Ronak Shah

Reputation: 388982

You cannot directly apply paste to a dataframe for your case here, to get the desired output you need to apply paste in two levels.

paste(apply(df, 1, function(x) paste(x, collapse = "$")), collapse = "%")

#[1] "1$L$11$Y%2$L$22$N%3$F$33$Y%4$L$44$Y"

Where the apply command creates a row-wise vector

apply(df, 1, function(x) paste(x, collapse = "$"))
#[1] "1$L$11$Y" "2$L$22$N" "3$F$33$Y" "4$L$44$Y"

and the next paste command merge these all together with collapse argument as "%".

Upvotes: 2

Tim Biegeleisen
Tim Biegeleisen

Reputation: 521289

Here is an alternative to the approach you used:

df_call <- c(df, sep="$")
paste(do.call(paste, df_call), collapse="%")

[1] "1$L$11$Y%2$L$22$N%3$F$33$Y%4$L$44$Y"

Demo

Upvotes: 3

Related Questions