R: Как найти и сравнить определенный элемент между двумя текстовыми файлами CSV - PullRequest
1 голос
/ 02 февраля 2020

Я нашел несколько похожих вопросов, таких как этот (о сравнении атрибутов в XML файлах), этот (о случае, когда сравниваемые значения являются цифрами c ) и этот (о получении количества столбцов, которые различаются между двумя файлами), но ничего об этой конкретной проблеме.

У меня есть два текстовых файла CSV, в которых много, но не все, строки равны. Файлы имеют одинаковое количество столбцов с одинаковым типом данных в столбцах, но не имеют одинаковое количество строк. Количество строк в обоих файлах составляет около 120 КБ, и в обоих файлах есть строки, которых нет в других.

Упрощенные версии этих файлов будут выглядеть, как показано ниже.

Файл 1:

PROFILE.ID,CITY,STATE,USERID
2265,Miami,Florida,EL4950
4350,Nashville,Tennessee,GW7420
5486,Durango,Colorado,BH9012
R719,Flagstaff,Arizona,YT7460
Z551,Flagstaff,Arizona,ML1451

Файл 2:

PROFILE.ID,CITY,STATE,USERID
1173,Nashville,Tennessee,GW7420
2265,Miami,Florida,EL4950
R540,Flagstaff,Arizona,YT7460
T216,Durango,Colorado,BH9012

В реальных файлах многие значения USERID в первом файле также могут быть находится во втором файле (однако некоторые могут отсутствовать). Кроме того, хотя значения USERID для всех пользователей не изменились, их PROFILE.ID могли измениться.

Проблема в том, что мне нужно было бы найти строки, в которых изменился PROFILE.ID.

Я думаю, что для анализа в R мне понадобится следующая последовательность шагов:

  1. Загрузка обоих файлов в R Studio в виде фреймов данных
  2. L oop через столбец USERID в первом файле (который содержит больше строк)
  3. Поиск во втором файле для каждого USERID, найденного в первом файле
  4. Возврат соответствующего PROFILE.ID из второго file
  5. Сравните возвращаемое значение с тем, что находится в первом файле
  6. Выведите строки, где значения PROFILE.ID отличаются

Я думал написать что-то вроде код, показанный ниже, но я не уверен, есть ли лучшие способы сделать это sh.

library(tidyverse)

con1  <- file("file1.csv", open = "r")
con2  <- file("file2.csv", open = "r")

file1 <- read.csv(con1, fill = F, colClasses = "character")
file2 <- read.csv(con2, fill = F, colClasses = "character")

for (i in seq(nrow(file1))) {
   profIDFile1 <- file1$PROFILE.ID[i]
   userIDFile1 <- file1$USERID[i]

   profIDRowFile2 <- filter(file2, USERID == userIDFile1)
   profIDFile2 <- profIDRowFile2$PROFILE.ID

   if (profIDFile1 != profIDFile2) {
     output < - profIDRowFile2
   }

}

write.csv(output, file='result.csv', row.names=FALSE, quote=FALSE)

close(con1)
close(con2)

Вопрос: Есть ли в R пакет, который может выполнить такое сравнение или что было бы хорошим способом выполнить это 1061 * в R скрипт?

Ответы [ 2 ]

3 голосов
/ 02 февраля 2020

Я думаю, что вы можете сделать это с помощью простого объединения:

library(dplyr)
full_join(file1, file2, by = "USERID") %>%
  filter(PROFILE.ID.x != PROFILE.ID.y)
#   PROFILE.ID.x    CITY.x   STATE.x USERID PROFILE.ID.y    CITY.y   STATE.y
# 1         4350 Nashville Tennessee GW7420         1173 Nashville Tennessee
# 2         5486   Durango  Colorado BH9012         T216   Durango  Colorado
# 3         R719 Flagstaff   Arizona YT7460         R540 Flagstaff   Arizona

Это показывает, что эти три строки USERID имеют различные поля PROFILE.ID. (.x от file1, .y от file2.)

Этот тест не очень хорошо работает с идентификаторами, отсутствующими в одном, так что вы можете добавить логи c такие as:

full_join(file1, file2, by = "USERID") %>%
  filter(is.na(PROFILE.ID.x) | is.na(PROFILE.ID.y) |
           PROFILE.ID.x != PROFILE.ID.y)
#   PROFILE.ID.x    CITY.x   STATE.x USERID PROFILE.ID.y    CITY.y   STATE.y
# 1         4350 Nashville Tennessee GW7420         1173 Nashville Tennessee
# 2         5486   Durango  Colorado BH9012         T216   Durango  Colorado
# 3         R719 Flagstaff   Arizona YT7460         R540 Flagstaff   Arizona
# 4         Z551 Flagstaff   Arizona ML1451         <NA>      <NA>      <NA>

В четвертой строке указан идентификатор, отсутствующий в file2. Это, вероятно, артефакт небольшого выборочного набора данных (что хорошо для SO :-), я не уверен, что это интересно или значимо для вас.

0 голосов
/ 02 февраля 2020

Мы можем сделать это с base R

subset(merge(file, file2, by = 'USERID'), PROFILE.ID.x != PROFILE.ID.y)
...