Erreur Cut () - les 'pauses' ne sont pas uniques

J'ai le dataframe suivant:

 a         
    ID   a.1    b.1     a.2   b.2
1    1  40.00   100.00  NA    88.89
2    2  100.00  100.00  100   100.00
3    3  50.00   100.00  75    100.00
4    4  66.67   59.38   NA    59.38
5    5  37.50   100.00  NA    100.00
6    6  100.00  100.00  100   100.00

Lorsque j'applique le code suivant à ce dataframe:

 temp <- do.call(rbind,strsplit(names(df)[-1],".",fixed=TRUE))
 dup.temp <- temp[duplicated(temp[,1]),]

 res <- lapply(dup.temp[,1],function(i) {
 breaks <- c(-Inf,quantile(a[,paste(i,1,sep=".")], na.rm=T),Inf)
 cut(a[,paste(i,2,sep=".")],breaks)
 })

La fonction cut () donne une erreur:

 Error in cut.default(a[, paste(i, 2, sep = ".")], breaks) : 
 'breaks' are not unique

Cependant, le même code fonctionne parfaitement sur un dataframe similaire:

 varnames<-c("ID", "a.1", "b.1", "c.1", "a.2", "b.2", "c.2")

 a <-matrix (c(1,2,3,4, 5, 6, 7), 2,7)

 colnames (a)<-varnames

 df<-as.data.frame (a)


    ID  a.1  b.1  c.1  a.2  b.2  c.2
  1  1    3    5    7    2    4    6
  2  2    4    6    1    3    5    7

 res <- lapply(dup.temp[,1],function(i) {
 breaks <- c(-Inf,quantile(a[,paste(i,1,sep=".")], na.rm=T),Inf)
 cut(a[,paste(i,2,sep=".")],breaks)
 })

 res
[[1]]
[1] (-Inf,3] (-Inf,3]
Levels: (-Inf,3] (3,3.25] (3.25,3.5] (3.5,3.75] (3.75,4] (4, Inf]

[[2]]
[1] (-Inf,5] (-Inf,5]
Levels: (-Inf,5] (5,5.25] (5.25,5.5] (5.5,5.75] (5.75,6] (6, Inf]

[[3]]
[1] (5.5,7] (5.5,7]
Levels: (-Inf,1] (1,2.5] (2.5,4] (4,5.5] (5.5,7] (7, Inf]

Quelle est la raison de cette erreur? Comment peut-il être fixé? Merci.

29
r
demandé sur DSSS 2013-04-24 10:33:33

4 réponses

Vous obtenez cette erreur car les valeurs quantiles dans vos données pour les colonnes b.1, a.2 et b.2 sont les mêmes pour certains niveaux, donc ils ne peuvent pas être directement utilisés comme valeurs de rupture dans la fonction cut().

apply(a,2,quantile,na.rm=T)
       ID      a.1    b.1   a.2      b.2
0%   1.00  37.5000  59.38  75.0  59.3800
25%  2.25  42.5000 100.00  87.5  91.6675
50%  3.50  58.3350 100.00 100.0 100.0000
75%  4.75  91.6675 100.00 100.0 100.0000
100% 6.00 100.0000 100.00 100.0 100.0000

Une façon de résoudre ce problème serait de mettre quantile() à l'intérieur de la fonction unique() - de sorte que vous supprimerez toutes les valeurs quantiles qui ne sont pas uniques. Cela fera bien sûr Moins de points de rupture si les quantiles ne sont pas uniques.

res <- lapply(dup.temp[,1],function(i) {
  breaks <- c(-Inf,unique(quantile(a[,paste(i,1,sep=".")], na.rm=T)),Inf)
  cut(a[,paste(i,2,sep=".")],breaks)
})

[[1]]
[1] <NA>        (91.7,100]  (58.3,91.7] <NA>        <NA>        (91.7,100] 
Levels: (-Inf,37.5] (37.5,42.5] (42.5,58.3] (58.3,91.7] (91.7,100] (100, Inf]

[[2]]
[1] (59.4,100]  (59.4,100]  (59.4,100]  (-Inf,59.4] (59.4,100]  (59.4,100] 
Levels: (-Inf,59.4] (59.4,100] (100, Inf]
27
répondu Didzis Elferts 2013-04-24 06:56:22

Si vous préférez garder le nombre de quantiles, une autre option consiste à ajouter un peu de gigue, par exemple

breaks = c(-Inf,quantile(a[,paste(i,1,sep=".")], na.rm=T),Inf)
breaks = breaks + seq_along(breaks) * .Machine$double.eps
8
répondu eddi 2013-11-07 20:47:16

Au lieu de couper, vous pouvez utiliser .bincode, qui accepte un vecteur non unique de ruptures.

8
répondu Matthew 2014-10-10 18:39:52

Si vous voulez dire les portions de 10% ou 25% de votre population quand vous dites décile, quartile, etc. et pas les valeurs numériques réelles des compartiments décile/quartile, vous pouvez classer vos valeurs en premier, et appliquer la fonction quantile sur les rangs:

a <- c(1,1,1,2,3,4,5,6,7,7,7,7,99,0.5,100,54,3,100,100,100,11,11,12,11,0)
a_ranks <- rank(a, ties.method = "first")
decile <- cut(a_ranks, quantile(a_ranks, probs=0:10/10), include.lowest=TRUE, labels=FALSE)  
4
répondu user3878033 2018-04-21 14:01:01