Как заменить пропущенные (не NA) данные на ноль - PullRequest
0 голосов
/ 20 ноября 2011

У меня есть набор данных, который выглядит следующим образом:

ByYear <- data.frame( V1 = c(2005,2006,2007,2008,2005,2006,2008,2006,2007,2005,2006,2007,2008),
                      V2 = c(0.5,0.2,1,1.6,2,5,8,4,3,6,8,6,5), 
                      V3 = c('A','A','A','A','B','B','B','C','C','D','D','D','D'))

Что дает мне

> ByYear
   V1   V2  V3
1  2005 0.5 A
2  2006 0.2 A
3  2007 1.0 A
4  2008 1.6 A
5  2005 2.0 B
6  2006 5.0 B
7  2008 8.0 B
8  2006 4.0 C
9  2007 3.0 C
10 2005 6.0 D
11 2006 8.0 D
12 2007 6.0 D
13 2008 5.0 D

Некоторые годы отсутствуют в V1.Это связано с ошибкой ввода данных.Я знаю, что это деликатный вопрос, но я точно знаю, что в этом случае пропущенный год в V1 означает, что значение в V2 должно быть 0.

Есть ли способ создать новый набор данных, которыйдобавляет строку с нулевым значением к любому отсутствующему году, например:

> ByYear
  V1   V2  V3
  2005 0.5 A
  2006 0.2 A
  2007 1.0 A
  2008 1.6 A
  2005 2.0 B
  2006 5.0 B
  2007 0.0 B
  2008 8.0 B
  2005 0.0 C
  2006 4.0 C
  2007 3.0 C
  2008 0.0 C
  2005 6.0 D
  2006 0.0 D
  2007 6.0 D
  2008 5.0 D

Спасибо всем за помощь!

Ответы [ 5 ]

1 голос
/ 21 ноября 2011

Используйте table, чтобы найти отсутствующие комбинации года / группы.

Frequencies <- with(ByYear, as.data.frame(table(V1, V3)))
MissingValues <- subset(Frequencies, Freq == 0, c(V1, V3))

Установите значение V2 равным 0 (или NA или как хотите), затем добавьтеэто к вашему исходному набору данных.

MissingValues$V2 <- 0
rbind(ByYear, MissingValues)
1 голос
/ 20 ноября 2011

Есть несколько способов сделать это, и самый простой - просто индексировать.

Давайте сначала создадим некоторые данные:

R> X <- data.frame(year=seq(2000,2010,by=1), val=0)
R> V <- data.frame(year=c(2003,2005,2007), val=c(1:3))

И давайте посмотрим на это

R> X
   year val
1  2000   0
2  2001   0
3  2002   0
4  2003   0
5  2004   0
6  2005   0
7  2006   0
8  2007   0
9  2008   0
10 2009   0
11 2010   0
R> V
  year val
1 2003   1
2 2005   2
3 2007   3

Итак, теперь мы хотим ввести V в X в нужных местах. Логическое совпадение, где V появляется в X, делает это возможным:

R> X[ X$year %in% V$year, "val"] <- V$val

Посмотрите на результат X$year %in% V$year в изоляции:

R> X$year %in% V$year
 [1] FALSE FALSE FALSE FALSE FALSE  TRUE FALSE  TRUE FALSE FALSE FALSE

Итак, теперь результат:

R> X
   year val
1  2000   0
2  2001   0
3  2002   0
4  2003   1
5  2004   0
6  2005   2
7  2006   0
8  2007   3
9  2008   0
10 2009   0
11 2010   0
R> 

Предостережение: вам нужны регулярные индексы, чтобы это работало. Годы или кварталы или месяцы работы. Рабочие дни труднее, но есть и другие методы.

0 голосов
/ 21 ноября 2011

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

y <- reshape(ByYear, direction = 'wide', timevar = 'V1', v.names = 'V2', idvar = 'V3')
y <- reshape(y, direction = 'long')
y$V3[is.na(y$V3)] <- 0

Вот еще одна, которая просто использует замену.Сначала вы создаете новый data.frame (df), который содержит полные V1 и V3, но с V2, установленным в 0.

uV1 <- unique(ByYear$V1)
uV3 <- unique(ByYear$V3)
df <- data.frame(V1 = rep(uV1, length(uV3)), V3 = rep(uV3, each = length(uV1)), V2 = 0)

Это также помогает путем создания новой переменной взаимодействия, чтобы вы могли иметьодин уникальный идентификатор каждой строки.

df$i <- interaction(df$V1, df$V3)
ByYear$i <- interaction(ByYear$V1, ByYear$V3)

А теперь в новом data.frame замените V2 на V2 из ByYear.

df$V2[df$i %in% ByYear$i] <- ByYear$V2
0 голосов
/ 20 ноября 2011

Наивный (не векторизованный) подход:

for (year in 2001:2010) {
   if (sum(ByYear["V1"]==year) == 0) {
      # add zero value for the found year
   }
}
0 голосов
/ 20 ноября 2011

Я пытался придумать простой набор тестов, чтобы заставить предложение Дирка работать, но повторяющаяся последовательность с пропущенными значениями поставила меня в тупик.Грубая сила казалась слишком многообещающей.Определите «внутренние» пропущенные значения, а затем определите промежутки на обоих концах, где увеличение на 1 может привести к поломке

for(i in seq_along(ByYear$V1[2:nrow(ByYear)]) ) if(
        ByYear$V1[i+1] -ByYear$V1[i] > 1){
         ByYear <- rbind(ByYear[1:i, ], c(v1[i]+1,0), ByYear[(i+1):NROW(ByYear), ])}

for(i in seq_along(ByYear$V1[2:nrow(ByYear)]) ) if(  
        ByYear$V1[i] ==2007 & ByYear$V1[i+1] != 2008 ){
         ByYear <- rbind(ByYear[1:i, ], c(2008, 0), ByYear[(i+1):NROW(ByYear), ])}
# I think you need to fill in all the missing 2008's before the missing 2005's
for(i in seq_along(ByYear$V1[2:nrow(ByYear)]) ) if(
        ByYear$V1[i] ==2008 & ByYear$V1[i+1] != 2005 ){
         ByYear <- rbind(ByYear[1:i, ], c(2005, 0), ByYear[(i+1):NROW(ByYear), ])}

ByYear
      V1  V2
1   2005 0.5
2   2006 0.2
3   2007 1.0
4   2008 1.6
5   2005 2.0
6   2006 5.0
7   2007 0.0
71  2008 8.0
9   2005 0.0
8   2006 4.0
91  2007 3.0
12  2008 0.0
10  2005 6.0
11  2006 8.0
121 2007 6.0
13  2008 5.0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...