Reputation: 2051
I have two vectors:
vars <- c("SR", "PL")
vis <- c(1,2,3)
Based on these vectors I would like to create the following vector:
"SR.1" "SR.2" "SR.3" "PL.1" "PL.2" "PL.3"
With paste
I have the following result:
paste(vars, vis, sep=".")
[1] "SR.1" "PL.2" "SR.3"
How can I create the vector I need?
Upvotes: 105
Views: 59251
Reputation: 31
also in base R
levels(interaction(vars, vis, lex.order = TRUE))
[1] "PL.1" "PL.2" "PL.3" "SR.1" "SR.2" "SR.3"
lex.order
is only necessary to sort the results; it can be omitted if order of elements is not important
Upvotes: 0
Reputation: 51
Here is yet another option using base R
vars <- c("SR", "PL"); vis <- c(1,2,3)
c(sapply(vars, \(x) paste(x, vis, sep = ".")))
[1] "SR.1" "SR.2" "SR.3" "PL.1" "PL.2" "PL.3"
Upvotes: 0
Reputation: 23
The simplest solution will just be
paste0(vars,".", vis)
[1] "SR.1" "PL.2" "SR.3"
Upvotes: -6
Reputation: 323
option with dplyr copied from this link
fruits <- tibble(
type = c("apple", "orange", "apple", "orange", "orange", "orange"),
year = c(2010, 2010, 2012, 2010, 2010, 2012),
size = factor(
c("XS", "S", "M", "S", "S", "M"),
levels = c("XS", "S", "M", "L")
),
weights = rnorm(6, as.numeric(size) + 2)
)
All possible combinations, i.e. all are defined, but not necessarily present in the data
fruits %>% expand(type)
#> # A tibble: 2 x 1
#> type
#> <chr>
#> 1 apple
#> 2 orange
fruits %>% expand(type, size)
#> # A tibble: 8 x 2
#> type size
#> <chr> <fct>
#> 1 apple XS
#> 2 apple S
#> 3 apple M
#> 4 apple L
#> 5 orange XS
#> 6 orange S
#> 7 orange M
#> 8 orange L
b<-fruits %>% expand(type, size, year)
#> # A tibble: 16 x 3
#> type size year
#> <chr> <fct> <dbl>
#> 1 apple XS 2010
#> 2 apple XS 2012
#> 3 apple S 2010
#> 4 apple S 2012
#> 5 apple M 2010
#> 6 apple M 2012
#> 7 apple L 2010
#> 8 apple L 2012
#> 9 orange XS 2010
#> 10 orange XS 2012
#> 11 orange S 2010
#> 12 orange S 2012
#> 13 orange M 2010
#> 14 orange M 2012
#> 15 orange L 2010
#> 16 orange L 2012
Then a simple paste
b <- fruits %>% expand(type, size, year) %>%
mutate(., pasted=paste(type, size, year, sep="."))
Upvotes: 1
Reputation: 388982
Some other options with purrr
:
library(purrr)
cross(list(vars, vis)) %>% map_chr(paste, sep = ".", collapse = ".")
#[1] "SR.1" "PL.1" "SR.2" "PL.2" "SR.3" "PL.3"
We can also use cross2
cross2(vars, vis) %>% map_chr(paste, sep = ".", collapse = ".")
#[1] "SR.1" "PL.1" "SR.2" "PL.2" "SR.3" "PL.3"
Upvotes: 6
Reputation: 42544
This old question already has an accepted answer. But as it's being used as dupe target, I believe it's worthwhile to add a data.table
solution which uses the cross join function CJ()
:
library(data.table)
options(datatable.CJ.names=FALSE) # required with version version 1.12.0+
CJ(vars, vis)[, paste(V1, V2, sep =".")]
#[1] "PL.1" "PL.2" "PL.3" "SR.1" "SR.2" "SR.3"
In case the original order is important:
CJ(vars, vis, sorted = FALSE)[, paste(V1, V2, sep =".")]
#[1] "SR.1" "SR.2" "SR.3" "PL.1" "PL.2" "PL.3"
CJ()
has changed default behaviour with version 1.12.0As announced in the release notes of version 1.12.0 (Point 3) the default option options(datatable.CJ.names=TRUE)
has changed. CJ()
now auto-names its inputs exactly as data.table()
does.
So, the code above has to be amended for data.table
version 1.12.0 and above:
library(data.table) ### version 1.12.0+
CJ(vars, vis)[, paste(vars, vis, sep =".")]
and
CJ(vars, vis, sorted = FALSE)[, paste(vars, vis, sep =".")]
resp.
Upvotes: 14
Reputation: 651
Another option is to use the each
argument of rep
:
paste(rep(vars, each = length(vis)), vis, sep = ".")
I find this more straightforward than the solutions based on apply
or expand.grid
.
Upvotes: 55
Reputation: 83215
Another option using sprintf
in combination with expand.grid
:
eg <- expand.grid(vis, vars)
sprintf('%s.%s', eg[,2], eg[,1])
which gives:
[1] "SR.1" "SR.2" "SR.3" "PL.1" "PL.2" "PL.3"
Explanation:
expand.grid
you create all combinations of the two vectors.sprintf
pastes the two vectors together according to the specified format ('%s.%s'
). Each %s
part of the format is replaced by the elements of the vectors.Upvotes: 22
Reputation: 1448
To maintain the order of the requested strings in the question, you can use these two modifications of both methods:
Change order of vectors and combine in reverse order
apply(expand.grid(vis, vars), 1, function(x) paste(x[2], x[1], sep="."))
[1] "SR.1" "SR.2" "SR.3" "PL.1" "PL.2" "PL.3"
or transpose the matrix before converting to vector:
as.vector(t(outer(vars, vis, paste, sep=".")))
[1] "SR.1" "SR.2" "SR.3" "PL.1" "PL.2" "PL.3"
Upvotes: 9
Reputation: 49033
You can use this, but there may be a simpler solution :
R> apply(expand.grid(vars, vis), 1, paste, collapse=".")
[1] "SR.1" "PL.1" "SR.2" "PL.2" "SR.3" "PL.3"
expand.grid
gives back a data.frame
which when used with apply
, apply
will convert it to a matrix
. This is just unnecessary (and inefficient on large data). outer
gives a matrix
and also takes function argument. It'll be much efficient on huge data as well.
Using outer
:
as.vector(outer(vars, vis, paste, sep="."))
# [1] "SR.1" "PL.1" "SR.2" "PL.2" "SR.3" "PL.3"
Upvotes: 115