зоопарк: недопустимы пропущенные значения в ‘row.names’

#r #zoo

#r #зоопарк

Вопрос:

Я не уверен, почему я получаю <NA> в индексе, когда я использую MATCH с объектом zoo. Предположим, у меня есть следующее:

 a <- read.zoo(data.frame(date=as.Date('2011-12-31')   0:49, col1=seq(1,50), col2=seq(11,60)), FUN = as.Date)
mon <- read.zoo(data.frame(date=c(as.Date('2012-01-01'), as.Date('2012-02-01'), as.Date('2012-03-01')), mc=letters[1:3], mc2=LETTERS[1:3]), FUN = as.Date)
  

Затем я пытаюсь сопоставить:

 mon$matched <- a[MATCH(index(mon),index(a))]$col1
  

Затем я попытался просмотреть, как mon теперь выглядит, и получил сообщение об ошибке:

 View(mon)
Error in View : missing values in 'row.names' are not allowed
  

Просматривая mon дальше, я не уверен, откуда взялась дополнительная <NA> строка:

 mon
           mc   mc2  matched
2012-01-01 a    A    2      
2012-02-01 b    B    33     
2012-03-01 c    C    <NA>   
<NA>       <NA> <NA> <NA>   
  

Как правильно выполнить это сопоставление? Результат правильный, за исключением последней строки, в которой указаны все значения <NA> . Должно быть, я делаю что-то в корне неправильное здесь…

Комментарии:

1. Значит, в основном left_join a равен mon? если бы они были объектами xts, merge.xts(mon, a, join = "left") . Не уверен, почему вы получаете na. Возможно, @G. Гротендик ответит на этот вопрос, и он может знать, почему вы получаете NA.

2. Пропущенная запятая после последнего закрывающего paren в a[MATCH(index(mon),index(a))]$col1 и не было совпадения с последней датой в a , следовательно, NA

3. @42- Запятая ничего не изменила. Отсутствие совпадения с последней датой — это нормально. Я специально пытаюсь выяснить, почему в последней строке есть NA для индекса и всех данных.

Ответ №1:

Кажется, вы пытаетесь создать левое соединение. Для этого обычно используется merge . Два элемента аргумента, all = c(TRUE, FALSE) показанные в приведенном ниже коде, указывают, сохраняем ли мы несогласованные даты в mon и a соответственно.
библиотека (зоопарк)

 a <- zoo(cbind(col1 = 1:50, col2 = 11:60), as.Date("2011-12-31")   0:49)
mon <- zoo(cbind(mc = letters[1:3], mc2 = LETTERS[1:3]), 
           as.Date(c('2012-01-01', '2012-02-01', '2012-03-01')))

merge(mon, a, all = c(TRUE, FALSE))
  

предоставление:

            mc mc2 col1 col2
2012-01-01 a  A   2    12  
2012-02-01 b  B   33   43  
2012-03-01 c  C   <NA> <NA>
  

Если вы хотите только col1 , то:

 merge(mon, a, all = c(TRUE, FALSE))$col1
  

Если вам не нужна строка с NA, укажите FALSE, чтобы исключить несоответствующие даты из обоих mon и a :

 merge(mon, a, all = FALSE)
  

ИНДЕКСИРОВАНИЕ ПО ВРЕМЕНИ

Это также можно сделать, используя индексацию времени, подобную этой;

 result <- mon
result$col1 <- a$col1[time(mon)]  # does an implicit merge
result
  

предоставление:

            mc mc2 col1
2012-01-01 a  A   2   
2012-02-01 b  B   33  
2012-03-01 c  C   <NA>
  

Если вам не нужна строка NA, этого будет достаточно:

 a[time(mon)]
  

предоставление:

            col1 col2
2012-01-01    2   12
2012-02-01   33   43
  

СОВПАДЕНИЕ

1) Хотя вышеупомянутые подходы рекомендуются, MATCH если вы по какой-то причине хотите использовать MATCH , добавьте nomatch = 0 аргумент, чтобы он возвращал 0 вместо NA для несоответствий. Это приведет к тому, что индексация просто удалит это значение. Присвоение result$col1 будет выполнять неявное merge заполнение NA.

 result <- mon
result$col1 <- a$col1[MATCH(time(mon), time(a), nomatch = 0)]
result
  

предоставление:

            mc mc2 col1
2012-01-01 a  A   2   
2012-02-01 b  B   33  
2012-03-01 c  C   <NA>
  

result$dol1 может использоваться для получения просто col1 .

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

 result <- mon
result$col1 <- coredata(a$col1)[MATCH(time(mon), time(a))]
result
  

Другое

Обратите внимание, что в вопросе row.names упоминается как индекс времени, а не имена строк.

Комментарии:

1. Отличное объяснение, как обычно. Спасибо.

Ответ №2:

Если вы посмотрите на a объект, вы обнаружите, что даты заканчиваются на

 > a
           col1 col2
2011-12-31    1   11
2012-01-01    2   12
<snipped most of them>
2012-02-16   48   58
2012-02-17   49   59
2012-02-18   50   60
  

Итак, внутри создания matched вы получили :

  MATCH(index(mon),index(a))
[1]  2 33 NA
  

Это то, что создало строку из всех NA

 a[MATCH(index(mon),index(a)) ]
 #--------
           col1 col2
2012-01-01    2   12
2012-02-01   33   43
<NA>         NA   NA
  

из которого вы выбрали col1 элементы:

 a[MATCH(index(mon),index(a))]$col1
#2012-01-01 2012-02-01       <NA> 
#         2         33         NA 
  

[<- Функция в library zoo сильно отличается от обычных [<- методов. Вы можете изучить код с помощью:

  getAnywhere(`[<-.zoo` ) 
  

Он проверяет количество аргументов и определяет, какие из них вы указали, и соответствующим образом изменяет свою логику. В случае, подобном вашему, где указаны только аргументы x и i, выполняется процесс сопоставления, который приводит к дополнительной записи в векторе индекса и, следовательно, к созданию дополнительной строки. Возможно, это не преднамеренное действие, и, возможно, в какой-то момент процесса должно было быть применено na.omit . Один из авторов zoo, @G.Grothendeick, является постоянным участником здесь и, возможно, сможет прокомментировать дальше. Если это так, то его слово — закон. Если вы выполните na.omit, вы получите ожидаемый результат:

 mon$matched <- na.omit(a[MATCH(index(mon),index(a))]$col1)

> mon
           mc mc2 matched
2012-01-01 a  A   2      
2012-02-01 b  B   33     
2012-03-01 c  C   <NA> 
  

Комментарии:

1. Отличный ответ! Спасибо