Соответствие записей в R на основе разницы столбцов - PullRequest
0 голосов
/ 16 октября 2018

У меня есть этот фрейм данных:

df1<-data.frame(ID_NUMBER = c(7160015,22695229,22695230,7160016,7160017,22695198,7160018,22695199,7160019,22695200,7160020,22695232,7160030,22697153,22697158,7162962,22698039,22698041,7162964) 
, CalNumber = c(9662.37,9662.45,9663.41,9663.44,9665.97,9666.11,9667.04,9667.1,9667.87,9668.01,9668.74,9668.79,9868.2, 72719.75,72723.21,99774,99774.03,99776.11,99776.13)
,Inspection_Date = c('11/13/2009','10/8/2014','10/8/2014','11/13/2009','11/13/2009','10/8/2014','11/13/2009','10/8/2014','11/13/2009','10/8/2014','11/13/2009','10/8/2014','11/13/2009','10/8/2014','10/8/2014','11/13/2009','10/8/2014','10/8/2014','11/13/2009'))

Я пытаюсь сопоставить записи 10/08/2014 с записями 13/13/2009 на основе ближайшей близости к CalNumber (что является абсолютной разницей, что<= 1).Записи заказаны CalNumber.Наименьшее совпадение записей 13.11.2009 может быть до или после записи 10.08.2014.Как только запись 10/08/2014 сопоставляется с самой близкой записью 13.11.2009, эта запись 13.11.2009 больше не рассматривается для совпадений.</p>

Извините, если это сбивает с толку.Надеюсь, это объясняет это лучше.Вот как будет выглядеть итоговый набор результатов.

df1<-data.frame(ID_NUMBER = c(7160015,22695229,22695230,7160016,7160017,22695198,7160018,22695199,7160019,22695200,7160020,22695232,7160030,22697153,22697158,7162962,22698039,22698041,7162964) 
, CalNumber = c(9662.37,9662.45,9663.41,9663.44,9665.97,9666.11,9667.04,9667.1,9667.87,9668.01,9668.74,9668.79,9868.2, 72719.75,72723.21,99774,99774.03,99776.11,99776.13)
,Inspection_Date = c('11/13/2009','10/8/2014','10/8/2014','11/13/2009','11/13/2009','10/8/2014','11/13/2009','10/8/2014','11/13/2009','10/8/2014','11/13/2009','10/8/2014','11/13/2009','10/8/2014','10/8/2014','11/13/2009','10/8/2014','10/8/2014','11/13/2009')
,Diff = c(NA,0.08,0.03,NA,NA,0.14,NA,0.06,NA,0.14,NA,0.05,NA, NA,NA,NA,0.03,0.02,NA)
,MatchID = c(NA,7160015,7160016,NA,NA,7160017,NA,7160018,NA,7160019,NA,7160020,NA, NA,NA,NA,7162962,7162964,NA))

Конечный набор результатов содержит 2 дополнительных столбца.Diff (abs (CalNumber) <= 1), который является разницей abs самой близкой записи, основанной на CalNumber.MatchID, который является соответствующим ID_Number, который был ближайшей записью.Если 10/08/2014 не имеет совпадения <= 1, оно остается пустым.Все столбцы MatchID 13.11.2009 пусты.MatchID заполняется только для записей 10/08/2014 с самыми близкими совпадениями 13.11.2009. </p>

Заранее спасибо !!

Ответы [ 2 ]

0 голосов
/ 16 октября 2018

Благодаря ответу @ zack, я думаю, теперь я понимаю, что делает OP.Чтобы найти ближайшее совпадение, обычно можно использовать скользящее соединение:

setDT(df1)
df1[Inspection_Date == "10/8/2014", c("md", "mid") := 
  df1[Inspection_Date == "11/13/2009"][.SD, on=.(CalNumber), roll="nearest", 
    .(abs(x.CalNumber - i.CalNumber), x.ID_NUMBER)
  ]
]

# oh, and then wipe it out if diff > 1
df1[md > 1, c("md", "mid") := NA]


    ID_NUMBER CalNumber Inspection_Date Diff MatchID   md     mid
 1:   7160015   9662.37      11/13/2009   NA      NA   NA      NA
 2:  22695229   9662.45       10/8/2014 0.08 7160015 0.08 7160015
 3:  22695230   9663.41       10/8/2014 0.03 7160016 0.03 7160016
 4:   7160016   9663.44      11/13/2009   NA      NA   NA      NA
 5:   7160017   9665.97      11/13/2009   NA      NA   NA      NA
 6:  22695198   9666.11       10/8/2014 0.14 7160017 0.14 7160017
 7:   7160018   9667.04      11/13/2009   NA      NA   NA      NA
 8:  22695199   9667.10       10/8/2014 0.06 7160018 0.06 7160018
 9:   7160019   9667.87      11/13/2009   NA      NA   NA      NA
10:  22695200   9668.01       10/8/2014 0.14 7160019 0.14 7160019
11:   7160020   9668.74      11/13/2009   NA      NA   NA      NA
12:  22695232   9668.79       10/8/2014 0.05 7160020 0.05 7160020
13:   7160030   9868.20      11/13/2009   NA      NA   NA      NA
14:  22697153  72719.75       10/8/2014   NA      NA   NA      NA
15:  22697158  72723.21       10/8/2014   NA      NA   NA      NA
16:   7162962  99774.00      11/13/2009   NA      NA   NA      NA
17:  22698039  99774.03       10/8/2014 0.03 7162962 0.03 7162962
18:  22698041  99776.11       10/8/2014 0.02 7162964 0.02 7162964
19:   7162964  99776.13      11/13/2009   NA      NA   NA      NA

Я жестко кодирую конкретные даты, основанные на ОП ...

Я пытаюсь сопоставить08.10.2014 записи в записи от 13.11.2009 основаны на ближайшей близости к CalNumber (абсолютная разница которого составляет <= 1). </p>

... в то время как ответ Зака ​​более общийсравнивает даты.(Обратите внимание, что вы должны использовать правильный формат даты для этого, например, df1[, Inspection_Date := as.IDate(Inspection_Date, "%m/%d/%Y")])


Как это работает

Ключевой частью является объединение x[i, on=, roll=, j] из подмножества 2009 года x = df1[Inspection_Date == "11/13/2009"] и подмножества 2014 года i = .SD = df1[Inspection_Date == "10/8/2014"] на основе условий в on= и roll=.

Внутри j из x[i, on=, roll=, j] префиксы x.* и i.* могут использоваться для устранения неоднозначности общих имен столбцов.

0 голосов
/ 16 октября 2018

Я относительно новичок в data.table, поэтому терпите меня:

library(data.table)

dt1 <- data.table(df1)
dt2 <- copy(dt1)

setnames(dt2, c("ID_NUMBER", "CalNumber", "Inspection_Date"), c("ID_NUMBER2", "CalNumber2", "Inspection_Date2"))

dt2[dt1,
    .(ID_NUMBER,
      CalNumber,
      Inspection_Date,
      Diff = abs(CalNumber - CalNumber2),
      MatchID = ID_NUMBER2),
    on = .(Inspection_Date2 > Inspection_Date),
    allow.cartesian = TRUE
    ][,
      .SD[which.min(ifelse(is.na(Diff), Inf, Diff))],
      by = .(ID_NUMBER, CalNumber, Inspection_Date)
      ][,
        .(ID_NUMBER,
          CalNumber,
          Inspection_Date,
          Diff = ifelse(Diff > 1, NA, Diff),
          MatchID = ifelse(Diff > 1, NA, MatchID))
        ]

    ID_NUMBER CalNumber Inspection_Date Diff MatchID
 1:   7160015   9662.37      11/13/2009   NA      NA
 2:  22695229   9662.45       10/8/2014 0.08 7160015
 3:  22695230   9663.41       10/8/2014 0.03 7160016
 4:   7160016   9663.44      11/13/2009   NA      NA
 5:   7160017   9665.97      11/13/2009   NA      NA
 6:  22695198   9666.11       10/8/2014 0.14 7160017
 7:   7160018   9667.04      11/13/2009   NA      NA
 8:  22695199   9667.10       10/8/2014 0.06 7160018
 9:   7160019   9667.87      11/13/2009   NA      NA
10:  22695200   9668.01       10/8/2014 0.14 7160019
11:   7160020   9668.74      11/13/2009   NA      NA
12:  22695232   9668.79       10/8/2014 0.05 7160020
13:   7160030   9868.20      11/13/2009   NA      NA
14:  22697153  72719.75       10/8/2014   NA      NA
15:  22697158  72723.21       10/8/2014   NA      NA
16:   7162962  99774.00      11/13/2009   NA      NA
17:  22698039  99774.03       10/8/2014 0.03 7162962
18:  22698041  99776.11       10/8/2014 0.02 7162964
19:   7162964  99776.13      11/13/2009   NA      NA

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

Логика:

  • Первый набор скобок выполняет соединения левое неравенство dt1 с dt2, вычисляет переменную Diff.Синтаксис левого соединения data.table немного странный, но он берет все строки из dt2, которые соответствуют указанным в аргументе on 1018 *

  • Второй наборскобок получает записи, соответствующие минимальному значению в группе.Здесь значение является слегка измененной Diff переменной (см. этот пост, который я использовал для справки)

  • Третьи скобки присваивают NA Diff и MatchID значения, где min Diff было выше 1

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...