Tom
Tom

Reputation: 5052

How do I properly nest paste() functions in R?

Can you tell me why

paste(paste(c("first", "second"), collapse=", "), "third", collapse=" and ")

gives me

"first, second third"

instead of

"first, second and third"

? What would be the correct syntax to get the second output?

Upvotes: 1

Views: 1387

Answers (3)

Gavin Simpson
Gavin Simpson

Reputation: 174948

Explanation

It is a subtle difference in how you are calling the function. In

paste(c("first", "second"), collapse = ", ")

note that you are passing only one argument via ... which is a vector of length 2. This results in a vector of length 1 returned:

> paste(c("first", "second"), collapse = ", ")
[1] "first, second"

You then pass this length 1 vector and a second length 1 vector via ... in the outer paste(). In effect you are doing:

paste("first, second", "third", collapse = " and ")

As both supplied vectors are of length 1, there is nothing to collapse over, the two strings are just concatenated with the separator sep.

Hence, in the first case,

paste(c("first", "second"), collapse = ", ")

there is no second vector to paste values on to the first, hence paste() collapses the elements of the single vector c("first", "second") using ", " as the separator. But when you pass in two length 1 vectors, in

paste("first, second", "third", collapse = " and ")

the function concatenates the two strings into a single string "first, second third" using sep, and then as there is just a length 1 character, there is nothing to collapse over.

Specific solution

If all you want is the string "first, second, and third" and you have the inputs as per your example, just switch to using sep = ", and " instead:

paste(paste(c("first", "second"), collapse=", "), "third", sep = ", and ")

which gives

> paste(paste(c("first", "second"), collapse=", "), "third", sep = ", and ")
[1] "first, second, and third"

or

> paste(paste(c("first", "second"), collapse=", "), "third", sep = " and ")
[1] "first, second and third"

if you don't want the Oxford comma.

Summary

The easiest way to see how sep and collapse relate to the supplied inputs. Two examples are illustrative:

> paste(1:5, letters[1:5], LETTERS[1:5], sep = " ")
[1] "1 a A" "2 b B" "3 c C" "4 d D" "5 e E"
> paste(1:5, letters[1:5], LETTERS[1:5], sep = " ", collapse = "-")
[1] "1 a A-2 b B-3 c C-4 d D-5 e E"

We observe two features:

  1. sep applies element-wise to the input vectors, e.g. to 1, a, and A; then 2, b, and B; and so on.
  2. collapse applies to the result of the first paste step using sep if that results in a vector of length >= 2 by concatenating the elements with the separator given by the argument collapse. Without collapse, paste() can return a vector of multiple strings if given vector inputs, but with collapse specified only a length 1 character vector will be returned.

Upvotes: 7

thelatemail
thelatemail

Reputation: 93938

Let's break it down:

1st part:

> paste(c("first", "second"), collapse=", ")
#[1] "first, second"

2nd part:

> paste("first, second", "third", collapse=" and ")
#[1] "first, second third"

using sep= instead of collapse=

> paste("first, second","third",sep=" and ")
#[1] "first, second and third"

Therefore you can use:

> paste(paste(c("first", "second"), collapse=", "), "third",sep=", and ")
#[1] "first, second, and third"

Upvotes: 1

Tyler Rinker
Tyler Rinker

Reputation: 110062

Or use:

paste(paste(c("first", "second"), collapse=", "), "third", sep=", and ")
## "first, second, and third"

And see this blog post on pasting: http://trinkerrstuff.wordpress.com/2013/09/15/paste-paste0-and-sprintf-2/

Upvotes: 1

Related Questions