Au cours d'une simulation, j'ai créé plusieurs ensembles de données avec> 1 000 000 de variables. Cependant, certaines des valeurs de ces variables sont NA
et dans certains cas, même toutes les valeurs sont NA
. Maintenant, j'aimerais calculer la somme de toutes les valeurs des variables, mais je veux obtenir NA
si toutes les valeurs sont NA
.
Le problème avec le sum (x, na.rm = T)
ou sum (na.omit (x))
est, qu'il renvoie 0 si toutes les valeurs sont NA
. Ainsi, j'ai écrit ma propre fonction qui traite NA
de la manière attendue:
sumna <- function(x) { sumna <- NULL return(ifelse(all(is.na(x)), NA, sum(na.omit(x)))) }
Cependant, cette implémentation est plutôt lente. p>
Ainsi, je recherche une implémentation ou une fonction pré-implémentée qui résume les valeurs d'un vecteur, omet NA
et renvoie NA
si toutes les valeurs sont NA
.
Merci d'avance!
5 Réponses :
Merci beaucoup, je pense que c'est exactement ce dont j'ai besoin!
sum_
est lent? x = rnorm (1000000); microbenchmark (sumna (x), sum_ (x))
pour votre sumna ()
?
Vous pouvez utiliser colSums
. En supposant que vous n'ayez pas de colonne avec tous les 0,
ifelse(colSums(abs(df), na.rm = TRUE) == 0, NA, colSums(df, na.rm = TRUE))
Pourrait fonctionner. Mais dans le cas où certaines des valeurs numériques s'ajouteraient à 0, j'aurais des doutes sur l'utilisation.
Vous pouvez également sous-définir des valeurs en fonction du nombre de NA
dans x
sumna <- function(x) { c(NA, sum(x, na.rm = TRUE))[(sum(is.na(x)) != length(x)) +1] } sumna(c(1:10, NA)) #[1] 55 sumna(c(NA, NA, NA)) #[1] NA sumna(1:5) #[1] 15
Vous pouvez supprimer tous les NA et tester si la longueur est supérieure à 0.
sumna_c <- function(x) { ret <- sum(x, na.rm = TRUE) if(ret == 0 && all(is.na(x))) {NA} else {ret} }
Je pense que dans la plupart des cas, cela devrait être efficace si vous utilisez simplement sum (x, na .rm = TRUE)
et testez ensuite quand sum == 0
s'il n'y a que NA
comme:
sumna_a <- function(x) { x <- na.omit(x) if(length(x)) return(sum(x)) NA } #or sumna_b <- function(x) { if(length(na.omit(x))) return(sum(x, na.rm = TRUE)) NA }
Ce n'est pas une réponse, veuillez faire de cet article un article wiki .
il est plus rapide d'utiliser x [! is.na (x)]
pour des vecteurs simples, plutôt que na.omit ()
.
@MartinMorgan Sur mon PC et ma version R na.omit ()
est plus rapide que x [! Is.na (x)]
Ah; essayez y = rep (NA_real_, 1000000)
. De plus, je ne suis pas sûr de la question initiale de savoir si le problème concerne un million de variables ou un million de simulations pour chacune de quelques variables.
En comparant les méthodes publiées, il semble que la fonction user10488504 c est actuellement la plus performante pour les cas où votre somme est! = 0 et vous n'avez pas que des NA. Si vous n'avez que l ' Anti de NA, RonakShah et akrun sont bons:
sumna_Anti <- function(x) { sumna <- NULL return(ifelse(all(is.na(x)), NA, sum(na.omit(x)))) } sumna_RonakShah <- function(x) { c(NA, sum(x, na.rm = TRUE))[(sum(is.na(x)) != length(x)) +1] } sumna_akrun <- function(x) { if(all(is.na(x))) NA else sum(x, na.rm = TRUE) } sumna_user10488504_a <- function(x) { x <- na.omit(x) if(length(x)) return(sum(x)) NA } sumna_user10488504_b <- function(x) { if(length(na.omit(x))) return(sum(x, na.rm = TRUE)) NA } sumna_user10488504_c <- function(x) { ret <- sum(x, na.rm = TRUE) if(ret == 0 && all(is.na(x))) {NA} else {ret} } set.seed(0) x <- rnorm(99999) library(microbenchmark) microbenchmark(sumna_Anti(x), sumna_RonakShah(x), sumna_akrun(x), sumna_user10488504_a(x), sumna_user10488504_b(x), sumna_user10488504_c(x) ) expr min lq mean median uq max neval cld sumna_Anti(x) 307.288 310.0280 390.01838 319.2800 410.2040 2056.284 100 d sumna_RonakShah(x) 245.251 247.4715 269.40054 253.1650 259.7850 393.495 100 bc sumna_akrun(x) 165.998 167.5005 209.39315 171.8925 190.8330 1768.761 100 b sumna_user10488504_a(x) 221.275 222.6740 315.93037 229.0330 263.6405 1944.602 100 cd sumna_user10488504_b(x) 224.614 225.8170 261.77913 231.2305 234.6465 1934.120 100 bc sumna_user10488504_c(x) 83.367 84.2610 86.16793 84.5900 86.4585 119.629 100 a x[sample(1:99999, 100)] <- NA microbenchmark(sumna_Anti(x), sumna_RonakShah(x), sumna_akrun(x), sumna_user10488504_a(x), sumna_user10488504_b(x), sumna_user10488504_c(x) ) expr min lq mean median uq max neval cld sumna_Anti(x) 607.367 628.4000 907.53974 634.3195 692.0845 4205.011 100 d sumna_RonakShah(x) 246.992 251.1290 273.80595 254.6195 261.4470 455.446 100 b sumna_akrun(x) 167.058 168.5790 196.13280 170.4125 186.2650 373.708 100 ab sumna_user10488504_a(x) 517.615 539.2940 684.20267 543.6295 582.5330 2360.247 100 c sumna_user10488504_b(x) 523.769 544.6195 869.76645 558.0240 1125.6725 3914.266 100 d sumna_user10488504_c(x) 84.142 85.2940 89.04266 86.4255 87.4020 207.624 100 a x = rep(NA_real_, 99999) microbenchmark(sumna_Anti(x), sumna_RonakShah(x), sumna_akrun(x), sumna_user10488504_a(x), sumna_user10488504_b(x), sumna_user10488504_c(x) ) sumna_Anti(x) 243.848 252.3825 308.2693 260.5285 286.8025 2198.275 100 a sumna_RonakShah(x) 242.706 249.3855 287.1426 258.8390 278.5905 1882.114 100 a sumna_akrun(x) 240.459 244.9125 269.2847 255.1230 274.9215 409.886 100 a sumna_user10488504_a(x) 1241.069 1285.3075 1534.1261 1343.7185 1486.4220 3117.453 100 ab sumna_user10488504_b(x) 1244.580 1281.9825 2461.2302 1349.9840 1427.9640 97590.279 100 b sumna_user10488504_c(x) 320.084 323.1905 353.9885 340.3555 358.7490 478.537 100 a
Pouvez-vous expliquer ce que vous entendez par «plutôt lent»? Il faut environ 5 à 10 fois plus de temps pour générer un million d'écarts aléatoires
x <- rnorm (1000000)
que pour appliquersumna (x)
etsumna ( x)
prend quelques millisecondes, donc je suppose que la plupart de votre temps de calcul est dans les simulations plutôt que dans cette étape?