En supposant que j'ai un cadre de données df
> dput(df)
structure(list(x = c("X", "X", "X", "Y", "Y", "Z", "Z", "Z"),
y = c("A", "B", "C", "B", "C", "A", "C", "D")), class = "data.frame", row.names = c(NA,
-8L))
> df
x y
1 X A
2 X B
3 X C
4 Y B
5 Y C
6 Z A
7 Z C
8 Z D
et générer une liste u1
comme ci-dessous
u1 <- with(
df,
tapply(y, x, combn, 2, toString)
)
où
> u1
$X
[1] "A, B" "A, C" "B, C"
$Y
[1] "B, C"
$Z
[1] "A, C" "A, D" "C, D"
> str(u1)
List of 3
$ X: chr [1:3(1d)] "A, B" "A, C" "B, C"
$ Y: chr [1(1d)] "B, C"
$ Z: chr [1:3(1d)] "A, C" "A, D" "C, D"
- attr(*, "dim")= int 3
- attr(*, "dimnames")=List of 1
..$ : chr [1:3] "X" "Y" "Z"
Quand j'ai couru stack(u1)
, j'aurai l'erreur suivante
> stack(u1)
Error in stack.default(u1) : at least one vector element is required
Il semble que je ne puisse pas utiliser stack
sur la sortie de tapply
directement même s'il s'agit d'une liste nommée.
Cependant, lorsque j'utilise u2 <- Map(c,u1)
pour post-traitement, les choses obtiennent des choses à nouveau
> u2 <- Map(c, u1)
> u2
$X
[1] "A, B" "A, C" "B, C"
$Y
[1] "B, C"
$Z
[1] "A, C" "A, D" "C, D"
> str(u2)
List of 3
$ X: chr [1:3] "A, B" "A, C" "B, C"
$ Y: chr "B, C"
$ Z: chr [1:3] "A, C" "A, D" "C, D"
> stack(u2)
values ind
1 A, B X
2 A, C X
3 B, C X
4 B, C Y
5 A, C Z
6 A, D Z
7 C, D Z
Comme nous pouvons le constater, dans str(u2)
, les attributs sont filtrés, ce qui semble résoudre le problème.
Pourquoi u1
A échoué mais u2
A réussi? Y a-t-il une autre façon que je puisse utiliser tapply
sur u1
Sans post-traitement (comme Map(c, u1)
)?
Ou peut également utiliser as.vector/c
Pour supprimer les attributs et convertir le 1d
Vecteur à un vecteur sans attributs sombres
stack(lapply(u1, c))
values ind
1 A, B X
2 A, C X
3 B, C X
4 B, C Y
5 A, C Z
6 A, D Z
7 C, D Z
Selon ?stack
Notez que la pile s'applique à Vecteurs (comme déterminé par IS.Vector): Les colonnes non vectorielles (par exemple, facteurs) seront ignorées avec un avertissement.
Le is.vector
retourne FALSE
pour tous les éléments membres de 'U1'
> sapply(u1, is.vector)
X Y Z
FALSE FALSE FALSE
Comme @Gregortoomas mentionné à propos de l'argument simplify
dans tapply
, il existe également une option simplify
dans combn
qui est vrai par défaut. Si nous spécifions que FALSE
, il renvoie un list
et devrait fonctionner
u1 <- with(
df,
tapply(y, x, FUN = function(u) combn(u, 2, FUN = toString, simplify = FALSE))
)
> stack(u1)
values ind
1 A, B X
2 A, C X
3 B, C X
4 B, C Y
5 A, C Z
6 A, D Z
7 C, D Z
Cependant, cela fonctionne avec enframe
sur le 1d
vecteur aussi
library(tibble)
library(tidyr)
enframe(u1) %>%
unnest(value)
# A tibble: 7 × 2
name value
<chr> <chr>
1 X A, B
2 X A, C
3 X B, C
4 Y B, C
5 Z A, C
6 Z A, D
7 Z C, D