Concatenate rows of a data frame

While others have focused on why your code isn’t working and how to improve it, I’m going to try and focus more on getting the result you want. From your description, it seems you can readily achieve what you want using paste:

df <- data.frame(letters = LETTERS[1:5], numbers = 1:5, stringsAsFactors=FALSE)
paste(df$letters, df$numbers, sep=""))

## [1] "A1" "B2" "C3" "D4" "E5"

You can change df$letters to character using df$letters <- as.character(df$letters) if you don’t want to use the stringsAsFactors argument.

But let’s assume that’s not what you want. Let’s assume you have hundreds of columns and you want to paste them all together. We can do that with your minimal example too:

df_args <- c(df, sep="")
do.call(paste, df_args)

## [1] "A1" "B2" "C3" "D4" "E5"

EDIT: Alternative method and explanation:

I realised the problem you’re having is a combination of the fact that you’re using a factor and that you’re using the sep argument instead of collapse (as @adibender picked up). The difference is that sep gives the separator between two separate vectors and collapse gives separators within a vector. When you use df[1,], you supply a single vector to paste and hence you must use the collapse argument. Using your idea of getting every row and concatenating them, the following line of code will do exactly what you want:

apply(df, 1, paste, collapse="")

Ok, now for the explanations:

Why won’t as.list work?

as.list converts an object to a list. So it does work. It will convert your dataframe to a list and subsequently ignore the sep="" argument. c combines objects together. Technically, a dataframe is just a list where every column is an element and all elements have to have the same length. So when I combine it with sep="", it just becomes a regular list with the columns of the dataframe as elements.

Why use do.call?

do.call allows you to call a function using a named list as its arguments. You can’t just throw the list straight into paste, because it doesn’t like dataframes. It’s designed for concatenating vectors. So remember that dfargs is a list containing a vector of letters, a vector of numbers and sep which is a length 1 vector containing only “”. When I use do.call, the resulting paste function is essentially paste(letters, numbers, sep).
But what if my original dataframe had columns "letters", "numbers", "squigs", "blargs" after which I added the separator like I did before? Then the paste function through do.call would look like:

paste(letters, numbers, squigs, blargs, sep)

So you see it works for any number of columns.

Leave a Comment