R:如何定位和比较两个 CSV 文本文件之间的特定元素

R: How to locate and compare a particular element between two CSV text files

我发现了一些类似的问题,例如 this one (about comparing attributes in XML files), this one (about a case where the compared values are numeric) and (关于获取两个文件之间不同的列数),但与此特定问题无关。

我有两个 CSV 文本文件,其中许多(但不是所有)行都相等。这些文件在列上具有相同数据类型的相同数量的列,但它们没有相同数量的行。两个文件的行数都在 120K 左右,并且两个文件都有一些行不在另一个文件中。

这些文件的简化版本如下所示。

文件 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. 遍历第一个文件(有更多行)的 USERID
  3. 在第二个文件中搜索在第一个文件
  4. 中找到的每个 USERID
  5. Return 第二个文件
  6. 对应的PROFILE.ID
  7. 将返回值与第一个文件中的内容进行比较
  8. 输出 PROFILE.ID 值不同的行

我正在考虑编写如下所示的代码,但不确定是否有更好的方法来完成此操作。

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 中是否有可以进行此类比较的包,或者在 R 脚本中完成此比较的好方法是什么?

我想你可以通过简单的连接来做到这一点:

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。)

该测试不能很好地处理其中缺少的 ID,因此您可以添加如下逻辑:

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 中缺少 ID。这很可能是一个小样本数据集的产物(这在 SO 上很好 :-),我不确定这对你来说是否有趣或有意义。

我们可以用 base R

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