2017-10-17 4 views
1

Cette question est une extension de la réponse à this et this Voici un exemple df:Remplacer NAs dans le vecteur (A) avec des valeurs spécifiques d'un autre vecteur (B) et forcer la valeur copiée dans le vecteur (B) nas

 name score end.s time 
    1 a 1 NA 1 
    2 a 2 NA 2 
    3 a 3 NA 3 
    4 b 4 4 1 
    5 b 5 4 2 
    6 b 6 4 3 
    7 c 7 NA 1 
    8 c 8 NA 2 
    9 d 6 6 1 
    10 d 7 6 3 

Et la sortie je voudrais:

 name score end.s time 
    1 a 1 3 1 
    2 a 2 3 2 
    3 a NA 3 3 
    4 b 4 4 1 
    5 b 5 4 2 
    6 b 6 4 3 
    7 c 7 8 1 
    8 c NA 8 2 
    9 d 6 6 1 
    10 d 7 6 3 

Il y a deux caractéristiques de la transformation - prendre la dernière valeur de la colonne « score » pour remplacer les agences nationales dans la colonne « » end.s et en remplaçant cette valeur de la colonne 'score' par NA. J'ai pensé que je pourrais remplacer les NA en utilisant la syntaxe des messages précédents, mais cela ne fonctionne pas de cette façon une fois que j'ai jeté un coup d'oeil et réfléchi à ce sujet une seconde.

Je pensais qu'une fonction d'application serait la voie à suivre, mais je n'ai même pas réussi à embrouiller la première étape.

Répondre

2

Ce que vous voulez est un peu compliqué, donc la réponse:

library(dplyr) 
df %>% group_by(name) %>% mutate(help=last(score)) %>% 
    mutate(score = ifelse(is.na(end.s), c(score[-n()], NA), score)) %>% 
    mutate_at(vars(end.s), funs(ifelse(is.na(.), help, .))) %>% select(-help) 

## # A tibble: 10 x 4 
## # Groups: name [4] 
##  name score end.s time 
## <fctr> <int> <int> <int> 
## 1  a  1  3  1 
## 2  a  2  3  2 
## 3  a NA  3  3 
## 4  b  4  4  1 
## 5  b  5  4  2 
## 6  b  6  4  3 
## 7  c  7  8  1 
## 8  c NA  8  2 
## 9  d  6  6  1 
## 10  d  7  6  3 

données:

df <- structure(list(name = structure(c(1L, 1L, 1L, 2L, 2L, 2L, 3L,  
    3L, 4L, 4L), .Label = c("a", "b", "c", "d"), class = "factor"),  
     score = c(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 6L, 7L), end.s = c(NA, 
     NA, NA, 4L, 4L, 4L, NA, NA, 6L, 6L), time = c(1L, 2L, 3L,   
     1L, 2L, 3L, 1L, 2L, 1L, 3L)), .Names = c("name", "score",   
    "end.s", "time"), row.names = c("1", "2", "3", "4", "5", "6",   
    "7", "8", "9", "10"), class = "data.frame") 
1

Je crois que ce qui suit fait ce que vous voulez.

test <- do.call(rbind, lapply(split(test, test$name), function(x){ 
    i <- is.na(x$end.s) 
    x$end.s[i] <- x$score[nrow(x)] 
    if(any(i)) x$score[nrow(x)] <- NA 
    x 
})) 
row.names(test) <- NULL 
test 
1

Voici une autre option avec data.table

library(data.table) 
i1 <- setDT(df)[is.na(end.s), .I[.N], name]$V1 
df[is.na(end.s), end.s := score[.N], name][i1, score := NA][] 
#  name score end.s time 
# 1: a  1  3 1 
# 2: a  2  3 2 
# 3: a NA  3 3 
# 4: b  4  4 1 
# 5: b  5  4 2 
# 6: b  6  4 3 
# 7: c  7  8 1 
# 8: c NA  8 2 
# 9: d  6  6 1 
#10: d  7  6 3