2015-05-27 3 views
2

Мне нужно воссоздать исходные переменные очень большого фрейма данных (более 900 переменных). Вот пример того, что я пытаюсь сделать:Создать условные новые переменные в R

dat <- data.frame(
    id=c('user1','user2','user3'), 
    agePanel1=c(20,25,32), 
    agePanel2=c(21,NA,33), 
    favColPanel1=c('blue','red','blue'), 
    favColPanel2=c('red',NA,'red') 
    ) 

    id  agePanel1 agePanel2 favColPanel1 favColPanel2 
    1 user1  20  21   blue   red 
    2 user2  25  NA   red   NA 
    3 user3  32  33   blue   red 

Для каждой переменной, мне нужно создать новую переменную (возраст и favCol ниже), которое NA, когда есть данные панели и в противном случае первое групповое наблюдение. В случаях с неполными данными панели все значения панели должны быть установлены на NA. В результате этого примера будет выглядеть следующим образом:

 id age agePanel1 agePanel2 favCol favColPanel1 favColPanel2 
    1 user1 NA  20  21  NA  blue   red   
    2 user2 25  NA  NA  red   NA   NA   
    3 user3 NA  32  33  NA  blue   red  

Я начал пробовать что-то с dplyr и tidyr:

mutate(dat, age = ifelse(is.na(test$agePanel2),agePanel1,NA)) 

Я изо всех сил, чтобы найти способ, чтобы сделать петлю или что-то, что может автоматизировать этот процесс.

+0

Я чувствую, как ты уже это: 'Дат $ возраста <- IfElse (is.na (Даты $ agePanel2), Даты $ agePanel1, NA)' –

ответ

1

Это не самый прямой решение вашего исходного вопроса. Но мне кажется, что было бы желательно получить ваши данные в течение длительного времени. Тогда операция, которую вы хотите сделать (и большинство других), будет намного проще.

# required packages 
require(dplyr) 
require(tidyr) 
# get data in long format 
dat_long <- dat %>% 
    gather(key, value, -id) %>% 
    separate(key, c("key", "panel"), sep = "Panel") %>% 
    spread(key, value, convert = TRUE) %>% 
    arrange(id, panel) %>% 
    group_by(id) 
dat_long 
## Source: local data frame [6 x 4] 
## Groups: id 
## 
##  id panel age favCol 
## 1 user1  1 20 blue 
## 2 user1  2 21 red 
## 3 user2  1 25 red 
## 4 user2  2 NA  NA 
## 5 user3  1 32 blue 
## 6 user3  2 33 red 

# functon that does desired operation 
panel_fct <- function(x){ 
    ifelse(is.na(x[2]), x[1], as(NA, class(x))) 
} 
# use mutate_each to do desired operation 
dat_long %>% summarise_each(funs(panel_fct), -panel) 
## Source: local data frame [3 x 3] 
## 
##  id age favCol 
## 1 user1 NA  NA 
## 2 user2 25 red 
## 3 user3 NA  NA 

Конечно, вы можете объединить конечный результат обратно в исходные данные, но для большинства операций было бы желательно использовать длинные данные вместо этого.

dat_long %>% summarise_each(funs(panel_fct), -panel) %>% left_join(dat, by = "id") 
## Source: local data frame [3 x 7] 
## 
##  id age favCol agePanel1 agePanel2 favColPanel1 favColPanel2 
## 1 user1 NA  NA  20  21   blue   red 
## 2 user2 25 red  25  NA   red   NA 
## 3 user3 NA  NA  32  33   blue   red 
+0

Спасибо вам ответить на это было очень полезно и жаль за задержку, был занят в эти последние дни;) – leakciM

1

Вы можете перебрать имена групп столбцов, которые вы хотите управлять, делая манипуляции для каждого:

cols <- c("age", "favCol") 
for (col in cols) { 
    dat[,col] <- dat[,paste0(col, "Panel1")] 
    dat[!is.na(dat[,paste0(col, "Panel2")]), col] <- NA 
    dat[is.na(dat[,paste0(col, "Panel2")]),paste0(col, "Panel1")] <- NA 
} 
dat 
#  id agePanel1 agePanel2 favColPanel1 favColPanel2 age favCol 
# 1 user1  20  21   blue   red NA <NA> 
# 2 user2  NA  NA   <NA>   <NA> 25 red 
# 3 user3  32  33   blue   red NA <NA> 
1

Вы можете использовать Map

dat[c('age', 'favcol')] <-Map(function(x,y) { 
      indx <- rowSums(is.na(cbind(x,y))) 
      x[seq_along(x)*NA^!indx]}, dat[c(2,4)], dat[c(3,5)]) 
dat[rowSums(is.na(dat[2:5]))!=0,2:5] <- NA 
dat 
# id agePanel1 agePanel2 favColPanel1 favColPanel2 age favcol 
#1 user1  20  21   blue   red NA <NA> 
#2 user2  NA  NA   <NA>   <NA> 25 red 
#3 user3  32  33   blue   red NA <NA>