J'essaye de réécrire mon code pour ne pas contenir de boucles for ou ifelse. Le but est d'extraire une matrice contenant des 0 et des 1 en fonction de la variable mu et de la variable cinterval - pour générer un 1 si y0 tombe dans son 95e CI, et 0 y0 entre son 95e CI, et de même pour y1. Cela serait répété avec y0 et y1 pour un certain nombre de modules.

mu contient des valeurs pour y0 et y1; cinterval contient quatre lignes:

  1. limite inférieure du 95e CI pour y0
  2. limite supérieure du 95e CI pour y0
  3. limite inférieure du 95e CI pour y1
  4. limite supérieure du 95e CI pour y1

cinterval peut être programmé pour avoir n'importe quel nombre de modules:

cinterval.fn <- function(y0y1modules) {
  matrix(c(y0results, y1results) nrow=4, ncol=no.of.modules, byrow=T) #simplified from true code
  rownames(cinterval) <- c("y0 95LCI", "y0 95UCI", "y1 95LCI", "y1 95UCI")
  colnames(cinterval) <- paste('module', 1:length(cinterval[1,]), sep='.')
  return(cinterval)
}

> cinterval
         module.1 module.2  module.3
y0 95LCI 2.434602 1.784056  1.751713
y0 95UCI 5.988160 6.519465  6.833455
y1 95LCI 3.778811 2.681708  2.805293
y1 95UCI 9.228941 9.716476 10.258412

mu ressemble à ceci:

mu <- c(4, 8)
mu
y0 y1 
 4  8  

Le code que j'ai est:

incinterval.fn <- function(cov.xy, mu, n1, dr) {
  cinterval <- cintervaloutput.fn(cov.xy, mu, n1, dr) # Generates matrix with 95% CI values for y0 and y1 after modules
  y0 <- NULL   # Empty vector
  for (module.no in 1:ncol(cinterval)) {
    y0 <- cbind(y0, ifelse (cinterval[1, module.no] <= mu["y0"] || mu["y0"] <= cinterval[2, module.no], 1, 0))
  }            # If y0 inside CI, 1, else 0
  y1 <- NULL   # Empty vector
  for (module.no in 1:ncol(cinterval)) {
    y1 <- cbind(y1, ifelse (cinterval[3, module.no] <= mu["y1"] || mu["y1"] <= cinterval[4, module.no], 1, 0))
  }            # If y1 inside CI, 1, else 0
  incinterval <- rbind(y0, y1) # Combines vectors
  colnames(incinterval) <- paste('module', 1:length(cinterval[1,]), sep='.')
  return(incinterval)
}

Le résultat, incintervalle, ressemble à ceci:

     module.1 module.2 module.3
[y0]        1        1        1
[y1]        1        1        1

Toute aide avec un codage plus efficace à remplacer et sinon serait grandement appréciée! J'utilise actuellement 2 boucles for et ifeelse.

0
MBorg 16 nov. 2017 à 11:53

4 réponses

Meilleure réponse

Exemples de données:

cinterval <- data.frame(rbind(c(2.434602,1.784056,1.751713),
                                 c(5.988160,6.519465,6.833455),
                                 c(3.778811,2.681708,2.805293),
                                 c(9.228941,9.716476,10.258412)),
                   row.names = c("y0 L","y0 U","y1 L","y1 U") 
)
colnames(cinterval) <- paste0("module.",1:3)
mu <- c("y0" = 4, "y1" = 8)

Vous pouvez profiter de la vectorisation et comparer une valeur unique avec un vecteur

as.numeric(mu["y0"] >= cinterval[1,] & mu["y0"] <= cinterval[2,])

[1] 1 1 1

Fonctionne en conséquence pour "y1".

1
Ape 16 nov. 2017 à 09:24

En supposant que vos données d'entrée sont créées quelque chose comme:

mu = c(y0 = 4, y1 = 8)

cinterval <-
    data.frame(names = c("y0", "y0", "y1", "y1"),
               CI = c("LCI", "UCI", "LCI", "UCI"),
               module.1 = c(2.434602, 5.988160, 3.778811, 9.228941),
               module.2 = c(1.784056, 6.519465, 2.681708, 9.716476),
               module.3 = c(1.751713, 6.833455, 2.805293, 10.258412))

Ensuite, quelque chose comme ça pourrait faire ce que vous voulez:

sapply(seq_along(mu),
     function(y) {

          cis  <- cinterval[cinterval[["names"]] == names(mu)[y], -1:-2]

         apply(cis, 2, function(ci) {
              findInterval(mu[y], ci)
          })

})
0
Danny 16 nov. 2017 à 09:20

Merci à tous pour vos suggestions et commentaires.

J'ai pris la suggestion d'Ape car c'était la plus simple.

Le code est maintenant changé avec du texte en gras pour:

incinterval.fn <- function(cov.xy, mu, n1, dr) {
  cinterval <- cintervaloutput.fn(cov.xy, mu, n1, dr) # Generates matrix with 95% CI values for y0 and y1 after treatment modules (can be any number of modules))
  **incinterval <- rbind(as.numeric(mu["y0"] >= cinterval[1,] & mu["y0"] <= cinterval[2,]),
                        as.numeric(mu["y1"] >= cinterval[3,] & mu["y0"] <= cinterval[4,]))**
  colnames(incinterval) <- paste('module', 1:length(cinterval[1,]), sep='.')
  return(incinterval)
}

Au lieu d'utiliser des boucles for et ifelse, il utilise un moyen plus simple de répondre à la question en générant des vecteurs avec les opérateurs de comparaison.

0
MBorg 16 nov. 2017 à 13:50

Je ne sais pas à quel point vous dépendez de votre structure de données, mais je propose une approche différente.

Si vous structurez votre ensemble de données dans un autre format, vous pouvez facilement écrire le résultat de incinterval dans une variable supplémentaire.

Nouvelles données:

cinterval <-  data.frame(year = c(0, 0, 0, 1, 1, 1),
               LCI = c(2.434602, 1.784056, 1.751713, 3.778811, 2.681708, 2.805293),
               UCI = c(5.988160, 6.519465, 6.833455, 9.228941, 9.716476, 10.258412),
               module = c(1, 2, 3, 1, 2, 3)
               )

> cinterval
  year      LCI       UCI module
1    0 2.434602  5.988160      1
2    0 1.784056  6.519465      2
3    0 1.751713  6.833455      3
4    1 3.778811  9.228941      1
5    1 2.681708  9.716476      2
6    1 2.805293 10.258412      3

Maintenant, vous définissez mu

mu <- c("y0" = 4, "y1" = 8)

Et apply une courte condition ifelse sur vos lignes en utilisant findInterval pour obtenir une nouvelle colonne avec vos résultats:

cinterval$inCI <- apply(cinterval, 1, 
                        function(x) ifelse(x[1] == 0, findInterval(mu["y0"], x[2:3]), 
                                                      findInterval(mu["y1"], x[2:3]))
                        )

Votre sortie:

  year      LCI       UCI module inCI
1    0 2.434602  5.988160      1    1
2    0 1.784056  6.519465      2    1
3    0 1.751713  6.833455      3    1
4    1 3.778811  9.228941      1    1
5    1 2.681708  9.716476      2    1
6    1 2.805293 10.258412      3    1

Notez que findInterval renverra soit un 0 si la valeur mu était en dessous du CI, un 1 si elle était à l'intérieur, ou un 2 si elle était au-dessus du CI.

Cela peut devenir fastidieux lorsque vous traitez de nombreux years, mais cela est assez robuste pour inclure autant de modules que vous le souhaitez.

0
LAP 16 nov. 2017 à 10:13
47325290