Einfügen von zwei Vektoren mit Kombinationen aller Vektorelemente

74

Ich habe zwei Vektoren:

vars <- c("SR", "PL")
vis <- c(1,2,3)

Basierend auf diesen Vektoren möchte ich den folgenden Vektor erstellen:

"SR.1"  "SR.2"  "SR.3"  "PL.1"  "PL.2"  "PL.3"

Mit habe pasteich folgendes Ergebnis:

paste(vars, vis, sep=".")
 [1] "SR.1" "PL.2" "SR.3"

Wie kann ich den benötigten Vektor erstellen?

DSSS
quelle

Antworten:

87

Sie können dies verwenden, aber es gibt möglicherweise eine einfachere Lösung:

R> apply(expand.grid(vars, vis), 1, paste, collapse=".")
[1] "SR.1" "PL.1" "SR.2" "PL.2" "SR.3" "PL.3"

expand.gridgibt wieder ein , data.framedie mit , wenn verwendet apply, um applyes zu einem konvertieren matrix. Dies ist nur unnötig (und bei großen Datenmengen ineffizient). outergibt ein matrixund nimmt auch Funktionsargument. Es wird auch bei großen Datenmengen sehr effizient sein.

Verwenden von outer:

as.vector(outer(vars, vis, paste, sep="."))
# [1] "SR.1" "PL.1" "SR.2" "PL.2" "SR.3" "PL.3"
Juba
quelle
2
expand.gridgibt eine Tabelle , die sortiert werden können , wenn Sie die Bestellung sein wollen SR,SR,PL,PL...statt SR,PL,SR,PL.
RMF
25

Eine andere Möglichkeit besteht darin, das eachArgument zu verwenden rep:

paste(rep(vars, each = length(vis)), vis, sep = ".")

Ich finde das einfacher als die Lösungen, die auf applyoder basieren expand.grid.

ewancarr
quelle
1
Sehr elegante Lösung! Vielen Dank!
Megatron
14

Eine weitere Option sprintfin Kombination mit expand.grid:

eg <- expand.grid(vis, vars)
sprintf('%s.%s', eg[,2], eg[,1])

was gibt:

[1] "SR.1" "SR.2" "SR.3" "PL.1" "PL.2" "PL.3"

Erläuterung:

  • Mit expand.griderstellen Sie alle Kombinationen der beiden Vektoren.
  • sprintfFügt die beiden Vektoren gemäß dem angegebenen Format ( '%s.%s') zusammen. Jeder %sTeil des Formats wird durch die Elemente der Vektoren ersetzt.
Jaap
quelle
1
Ich denke, dies ist die eleganteste Lösung aller vorgeschlagenen!
JelenaČuklina
9

Um die Reihenfolge der angeforderten Zeichenfolgen in der Frage beizubehalten, können Sie diese beiden Modifikationen beider Methoden verwenden:

Ändern Sie die Reihenfolge der Vektoren und kombinieren Sie sie in umgekehrter Reihenfolge

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"

oder transponieren Sie die Matrix, bevor Sie sie in einen Vektor konvertieren:

as.vector(t(outer(vars, vis, paste, sep="."))) 
[1] "SR.1" "SR.2" "SR.3" "PL.1" "PL.2" "PL.3"
CCID
quelle
8

Diese alte Frage hat bereits eine akzeptierte Antwort. Da es jedoch als Dupe-Ziel verwendet wird, lohnt es sich meiner Meinung nach, eine data.tableLösung hinzuzufügen , die die Cross-Join- Funktion verwendet 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"

Falls die ursprüngliche Bestellung wichtig ist:

CJ(vars, vis, sorted = FALSE)[, paste(V1, V2, sep =".")]
#[1] "SR.1" "SR.2" "SR.3" "PL.1" "PL.2" "PL.3"

Bearbeiten: CJ()hat das Standardverhalten mit Version 1.12.0 geändert

Wie in den Versionshinweisen von Version 1.12.0 (Punkt 3) angekündigt, options(datatable.CJ.names=TRUE)hat sich die Standardoption geändert. CJ()Jetzt benennt es seine Eingaben automatisch genau as data.table().

Daher muss der obige Code für data.tableVersion 1.12.0 und höher geändert werden :

library(data.table)   ### version 1.12.0+
CJ(vars, vis)[, paste(vars, vis, sep =".")]

und

CJ(vars, vis, sorted = FALSE)[, paste(vars, vis, sep =".")]

bzw.

Uwe
quelle
1

Einige andere Optionen mit 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"

Wir können auch verwenden cross2

cross2(vars, vis) %>%  map_chr(paste, sep = ".", collapse = ".")
#[1] "SR.1" "PL.1" "SR.2" "PL.2" "SR.3" "PL.3"
Ronak Shah
quelle