2016-10-19 1 views
3

J'ai un ensemble de données avec trois colonnes: année, ville, valeur qui ressemble à ceci:R - Gardez données les plus récentes qui ne sont pas NA, à moins que NA disponible

year = c(2010, 2013, 2010, 2013, 2013) 
city = c("Berlin","Berlin", "Munich", "Munich", "Frankfurt") 
value = c(1234, NA, NA, 6372, NA) 
data <- data.frame(year, value1, value2) 

year city value 
1 2010 Berlin 1234 
2 2013 Berlin  NA 
3 2010 Munich  NA 
4 2013 Munich 6372 
5 2013 Frankfurt  NA 

Je voudrais savoir comment sous-ensemble cela pour que je ne conserver que les données les plus récentes qui est disponible, de sorte qu'à la fin, je suis parti avec des données comme ceci:

year city value 
1 2010 Berlin 1234 
2 2013 Munich 6372 
3 2013 Frankfurt  NA 

Si je sous-ensemble de l'année le plus, je reçois NAs où pour cette année, ISN 't données. Si je sous-ensemble sur !is.na(), je perds toutes les lignes où il ya seulement NA disponible.

Ce que je veux faire est d'obtenir plus précisément l'année le plus élevé pour une ville donnée avec les données, à moins qu'il n'y a que pour cette ville NAs, puis l'année le plus élevé avec NA. Comment pourrais-je m'y prendre?

+0

Que voulez-voulez-vous sous-ensemble? De votre exemple, il semble que vous ne voulez pas sous-ensemble pour l'année la plus élevée, y at-il une autre variable que vous ne montrez pas ici? –

+0

Ah, non: Je veux sous-ensemble pour la colonne ville: l'année la plus élevée avec des données pour une ville donnée, à moins qu'il n'y ait que des NA pour cette ville, puis l'année la plus élevée avec NA. Est-ce que cela le rend plus clair? – LukasKawerau

Répondre

3

Nous pouvons utiliser data.table. Convertir le 'data.frame' en 'data.table' (setDT(data)), groupé par 'ville', nous spécifions le 'i' comme 'année' en descendant order index, if il y a any non-NA 'valeur', nous sous-formons le 'Data.table' basé sur l'index de la première 'valeur' ​​non NA ou else retournons le sous-ensemble de Data.table.

library(data.table) 
setDT(data)[order(-year), if(any(!is.na(value))) 
      .SD[which(!is.na(value))[1L]] else .SD, by = city] 

Ou une option compacte par Arenburg où nous @ David obtenons l'indice de which.max

setDT(data)[order(-year), .SD[which.max(!is.na(value))], by = city] 

ou utiliser une modification à l'aide .I pour le rendre plus rapide

setDT(data)[data[order(-year), .I[which.max(!is.na(value))], by = city]$V1] 
+0

c'est vraiment génial, merci! J'ai essayé sur mon vrai jeu de données et cela a fonctionné parfaitement :) une question cependant: si j'ai plusieurs années pour une ville avec NA (ainsi 2010, Francfort, NA; 2011, Francfort, NA; 2013, Francfort, NA) il garde tout de ces années. Comment puis-je conserver seulement la dernière année pour ce cas? – LukasKawerau

+5

Ou tout simplement 'setDT (données) [ordre (-Year), .SD [which.max (! Is.na (valeur))], par ville =]' –

+0

@DavidArenburg qui était très bon. En fait, j'essayais similaire avec 'which'. Était sur un appel, donc ne pouvait pas se concentrer sur elle – akrun

1

Un plus bavard, approche du rond-point en utilisant dplyr. Il fonctionne également pour votre cas où vous avez plusieurs années de NA.

library(dplyr) 
data %>% 
    group_by(city) %>% 
    mutate(all_na = all(is.na(value)), 
     remove = ifelse(all_na, 
         year != max(year), 
         is.na(value))) %>% 
    ungroup() %>% 
    filter(!remove) %>% 
    select(-all_na, -remove) 
0

max_pos(x) renvoie la position dans x du dernier élément non-NA de x ou s'il n'y a pas d'éléments non-NA elle retourne la dernière position de x. is_max renvoie une logique qui est TRUE dans la position maximale et FALSE ailleurs. Notez que ave va contraindre son résultat au type de son premier argument donc nous utilisons !! pour le rendre logique. Finalement, nous sous-estimons ces éléments. Cela suppose que l'entrée est triée par année dans la ville comme c'est le cas dans la question.

Notez que max_pos a été rendu compact en utilisant ces faits:

  • dans le seq_along(x) * 0*x0*x est un vecteur de zéros et donc ajouter NAs nas les éléments correspondants de seq_along(x). Autrement dit, il donne le même résultat que replace(seq_along(x), is.na(x), NA) qui pourrait être utilisé à sa place.
  • which.max renvoie un résultat de longueur nulle si x est toutes les valeurs NA et c(arg1, arg2)[1] donne le même résultat que if (length(arg1) == 0) arg2 else arg1 qui pourrait être utilisé à sa place.

Aucun paquet n'est utilisé.

max_pos <- function(x) c(which.max(seq_along(x) + 0*x), length(x))[1] 
is_max <- function(x) seq_along(x) == max_pos(x) 
subset(data, !!ave(value, city, FUN = is_max)) 

donnant:

year  city value 
1 2010 Berlin 1234 
4 2013 Munich 6372 
5 2013 Frankfurt NA