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?

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"

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.


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.

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"

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.


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"
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.