#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
, следовательно, NA3. @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. Отличный ответ! Спасибо