J'ai parcouru un certain nombre de messages sur les facteurs de commande, mais je n'ai pas encore trouvé de solution à mon problème. Malheureusement, ma connaissance de R est encore assez rudimentaire.
J'ai un sous-ensemble d'un catalogue d'artefacts archéologiques avec lequel je travaille. J'essaie de croiser les types d'artefacts historiques de diagnostic et les emplacements de test de site. Assez facile avec ddply ou tapply.
Mon problème est que je veux trier les types d'artefacts (un facteur) par leur date de diagnostic moyenne (nombre/année), et je continue de les obtenir par ordre alphabétique. Je sais que je dois en faire un facteur ordonné, mais je ne sais pas comment le commander par la valeur de l'année dans l'autre colonne.
IDENTIFY MIDDATE
engine-turned fine red stoneware 1769
white salt-glazed stoneware, scratch blue 1760
wrought nail, 'L' head 1760
yellow lead-glazed buff earthenware 1732
...
Qui doit être commandé:
IDENTIFY MIDDATE
yellow lead-glazed buff earthenware 1732
white salt-glazed stoneware, scratch blue 1760
wrought nail, 'L' head 1760
engine-turned fine red stoneware 1769
...
Le facteur (IDENTIFY) doit être commandé par la date (MIDDATE). Je pensais l'avoir avec
Catalog$IDENTIFY<-factor(Catalog$IDENTIFY,levels=Catalog$MIDDATE,ordered=TRUE)
Mais recevez l'avertissement:
In `levels<-`(`*tmp*`, value = if (nl == nL) as.character(labels)
else paste0(labels,: duplicated levels will not be allowed
in factors anymore
IDENTIFY a ~ 130 niveaux de facteur et beaucoup ont la même valeur pour MIDDATE, donc je dois commander IDENTIFY by MIDDATE et une autre colonne TYPENAME.
Un peu plus en détail:
J'ai un dataframe Catalog
, qui se décompose (c'est-à-dire str(Catalog)
) comme:
> str(Catalog)
'data.frame': 2211 obs. of 15 variables:
$ TRENCH : Factor w/ 7 levels "DRT 1","DRT 2",..: 1 1 1 1 1 1 1 1 1 1 ...
$ U_TYPE : Factor w/ 3 levels "EU","INC","STP": 1 1 1 1 1 1 1 1 1 1 ...
$ U_LBL : Factor w/ 165 levels "001","005","007",..: 72 72 72 72 72 72 ...
$ L_STRAT : Factor w/ 217 levels "#2-7/25","[3]",..: 4 4 4 4 4 4 89 89 89 89 ...
$ START : num 0 0 0 0 0 0 39.4 39.4 39.4 39.4 ...
$ END : num 39.4 39.4 39.4 39.4 39.4 39.4 43.2 43.2 43.2 43.2 ...
$ Qty : int 1 1 3 5 1 1 6 8 1 1 ...
$ MATNAME : Factor w/ 6 levels "Ceramics","Chipped Stone",..: 1 1 1 5 5 6 ...
$ TYPENAME: Factor w/ 9 levels "Architectural Hardware",..: 9 9 9 1 1 3 9 ...
$ CATNAME : Factor w/ 32 levels "Biface","Bottle Glass",..: 24 29 29 6 24 ...
$ IDENTIFY: Factor w/ 112 levels "amethyst bottle glass",..: 17 91 96 71 103 ...
$ BEGDATE : int 1820 1820 1830 1835 1700 NA 1670 1762 1800 1720 ...
$ ENDDATE : int 1900 1970 1860 1875 1820 NA 1795 1820 1820 1780 ...
$ OCC_LBL : Ord.factor w/ 5 levels "Late 19th Century"<..: 2 1 2 2 4 5 4 3 ...
$ MIDDATE : num 1860 1895 1845 1855 1760 ...
Je dois faire de IDENTIFY
un facteur ordonné et réorganiser par MIDDATE
-> TYPENAME
-> alpha par IDENTIFY
.
Ce que je ne comprends pas vraiment, c'est comment réorganiser les commandes combinées à partir de plusieurs colonnes.
Je le ferais simplement dans la base de données, mais une grande partie de ce que j'exécute sont des moyens pondérés dans toutes sortes de tableaux croisés (par exemple, les profondeurs moyennes pondérées sous la surface du sol pour les classes d'artefacts par emplacement) ...
... faisable dans Access, mais désordonné et imprévisible. Beaucoup plus facile et plus propre à gérer dans R, mais je préfère ne pas avoir à trier manuellement les tableaux résultants.
Ce que j'essaie de produire, c'est un certain nombre de choses dans ce sens:
>xtab.Catalog<-tapply(Catalog$Qty,list(Catalog$IDENTIFY,Catalog$TRENCH),sum)
IDENTIFY DRT1 DRT2 DRT3 DRT4 DRT5 DRT6
Staffordshire stoneware 4 NA NA NA NA NA
undecorated delftware 6 4 NA NA NA NA
unidentified wrought nail 15 9 3 1 3 NA
white salt-glazed stoneware 6 1 1 NA 2 1
white salt-glazed scratch blue 1 NA NA NA NA NA
white stoneware, slip-dipped NA NA NA NA NA NA
wrought nail, 'L' head 2 NA NA NA NA NA
wrought nail, 'rose' head 62 21 4 NA 1 1
wrought nail, 'T' head 2 NA 1 NA NA 1
yellow lead-glazed 12 NA NA NA 1 3
...
... mais j'en ai besoin pour trier dans l'ordre logique (c'est-à-dire chronologique/type) au lieu de l'ordre alphabétique.
Voici un échantillon reproductible, avec solution:
set.seed(0)
a = sample(1:20,replace=F)
b = sample(1:20,replace=F)
f = as.factor(letters[1:20])
> a
[1] 18 6 7 10 15 4 13 14 8 20 1 2 9 5 3 16 12 19 11 17
> b
[1] 16 18 4 12 3 5 6 1 15 10 19 17 9 11 2 8 20 7 13 14
> f
[1] a b c d e f g h i j k l m n o p q r s t
Levels: a b c d e f g h i j k l m n o p q r s t
Maintenant pour le nouveau facteur:
fn = factor(f, levels=unique(f[order(a,b,f)]), ordered=TRUE)
> fn
[1] a b c d e f g h i j k l m n o p q r s t
20 Levels: k < l < o < f < n < b < c < i < m < d < s < q < g < h < e < ... < j
Trié sur "a", "b" suivant et enfin "f" lui-même (bien que dans cet exemple, "a" n'ait pas de valeurs répétées).
Je recommande l'approche basée sur dplyr suivante (h/t daattali ) qui peut être étendue à autant de colonnes que vous le souhaitez:
library(dplyr)
Catalog <- Catalog %>%
arrange(MIDDATE, TYPENAME) %>% # sort your dataframe
mutate(IDENTIFY = factor(IDENTIFY, unique(IDENTIFY))) # reset your factor-column based on that order
La fonction fct_reorder2
fait exactement cela.
Veuillez noter la subtilité que fct_reorder
est trié par ordre croissant pendant que fct_reordering2
est trié par ordre décroissant.
Code de la documentation:
df0 <- tibble::tribble(
~color, ~a, ~b,
"blue", 1, 2,
"green", 6, 2,
"purple", 3, 3,
"red", 2, 3,
"yellow", 5, 1
)
df0$color <- factor(df0$color)
fct_reorder(df0$color, df0$a, min)
#> [1] blue green purple red yellow
#> Levels: blue red purple yellow green
fct_reorder2(df0$color, df0$a, df0$b)