2016-01-26 2 views
0

у меня есть большой data.frame, который похож на примере ниже:Дублирование строк в data.frame в R

ID date sex grade location 
1 1 2000 m  1  x 
2 1 2001 m  2  y 
3 2 1999 f  3  z 
4 2 2000 f  4  f 
5 3 2000 m  5  k 
6 3 2001 m  6  l 

воспроизвести его запустить:

df <- data.frame(ID=c(1,1,2,2,3,3), 
        date=c(2000,2001,1999,2000,2000,2001), 
        sex = c("m", "m", "f", "f", "m", "m"), 
        grade =c(1,2,3,4,5,6), 
        location =c("x","y","z", "f","k","l")) 

Я готов манипулировать/изменить data.frame, чтобы получить следующую структуру:

 ID date sex grade location 
    1 1 1999 m  0  0 
    2 1 2000 m  1  x 
    3 1 2001 m  2  y 
    4 2 1999 f  3  z 
    5 2 2000 f  4  f 
    6 2 2001 f  0  0 
    7 3 1999 m  0  0 
    8 3 2000 m  5  k 
    9 3 2001 m  6  l 
+3

Почему вы хотите иметь '0' в столбце символов? Разве не было бы смысла? Даже в числовой колонке это может ввести вас в замешательство с реальными нулями. –

+0

Связано: http://stackoverflow.com/q/31150028/1191259 – Frank

ответ

5

Это может быть сделано с data.table следующим образом:

library(data.table) 
setDT(df, key = c("ID", "date")) 

> df[CJ(ID, date, unique = TRUE)] 
    ID date sex grade location 
1: 1 1999 NA NA  NA 
2: 1 2000 m  1  x 
3: 1 2001 m  2  y 
4: 2 1999 f  3  z 
5: 2 2000 f  4  f 
6: 2 2001 NA NA  NA 
7: 3 1999 NA NA  NA 
8: 3 2000 m  5  k 
9: 3 2001 m  6  l 

Если вы хотите объединить sex в ID:

df <- df[CJ(ID, date, unique = TRUE)] 

df[ , sex := unique(na.omit(sex)), by = ID] 

Если вы действительно хотите 0 сек вместо NA для grade и location (вы должны пересмотреть это, как это, вероятно, предпочтительнее, чтобы оставить его в качестве NA):

df[is.na(grade), grade := 0] 
levels(df$location) <- c("0", levels(df$location)) 
df[is.na(location), location := "0"] 
+0

Это довольно хороший способ. Можно ли сохранить значения переменной 'sex', чтобы она не менялась на ** NA **? –

+0

У вас есть уникальный аргумент в 'CJ' сейчас ... –

+0

@DavidArenburg аккуратный. – MichaelChirico

4

С tidyr, мы можем использовать complete

library(tidyr) 
library(dplyr) 
df %>% 
    complete(ID, date) 
# ID date sex grade location 
# (dbl) (dbl) (fctr) (dbl) (fctr) 
#1  1 1999  NA NA  NA 
#2  1 2000  m  1  x 
#3  1 2001  m  2  y 
#4  2 1999  f  3  z 
#5  2 2000  f  4  f 
#6  2 2001  NA NA  NA 
#7  3 1999  NA NA  NA 
#8  3 2000  m  5  k 
#9  3 2001  m  6  l 

Если нам нужно заменить значения NA в 'секс'

df %>% 
    complete(ID, date) %>% 
    group_by(ID) %>% 
    mutate(sex= sex[!is.na(sex)][1L]) 

Или base R вариант

merge(expand.grid(lapply(df[1:2], unique)), df, all.x=TRUE) 
Смежные вопросы