首页 > 解决方案 > 是否可以在 R 中比较多个 .csv 文件的内容

问题描述

假设我有一个包含 10 个 .csv 文件的文件夹,它们看起来像:

> df1
  apple Mary car
a     1    1   1
b     2    2   2
c     3    3   3
d     4    4   4
e     5    5   5

> df2
  apple Mary car
a     1    1   1
b     2    2   2
p     4    3   2
d     4    4   4
e     5    5   5

> df3
  phone Jognny car
a     1      1   1
b     2      2   2
c     3      3   3
p     4      3   4
e     5      5   5
i     1      2   3

我想知道dfs有多“相似”。例如,在 colnamesdf1df2有 100% 的匹配,但在 rownames 中只有 80% 的匹配。因此,两个数据帧的匹配率约为 87%(13/15 数据内容元素)。 df2并且df3只有 33% 的 colnames 匹配...等然后,df1然后df3...等

它类似于cor(),但有不同维度和名称的数据框...等

生成数据的代码:

> dput(df1)
structure(list(apple = 1:5, Mary = 1:5, car = 1:5), class = "data.frame", row.names = c("a", 
"b", "c", "d", "e"))
> dput(df2)
structure(list(apple = c(1, 2, 4, 4, 5), Mary = c(1, 2, 3, 4, 
5), car = c(1, 2, 2, 4, 5)), row.names = c("a", "b", "p", "d", 
"e"), class = "data.frame")
> dput(df3)
structure(list(phone = c(1, 2, 3, 4, 5, 1), Jognny = c(1, 2, 
3, 3, 5, 2), car = c(1, 2, 3, 4, 5, 3)), row.names = c("a", "b", 
"c", "p", "e", "i"), class = "data.frame")

标签: r

解决方案


您始终可以查看一个数据帧中的行名,这些行名也是另一个数据帧的行名:

table(colnames(df1) %in% colnames(df2))*100/ncol(df1)
#> TRUE 
#>  100 

table(rownames(df1) %in% rownames(df2))*100/nrow(df1)
#> FALSE  TRUE 
#>    20    80 

因此,您的“相似性度量”是有多少单元格具有相同的行名和列名,除以有多少单元格。单元格数是行数和列数的乘积;名称匹配的单元格数是名称匹配的行数和列数的乘积:

sum(rownames(df1) %in% rownames(df2)) * sum(colnames(df1) %in% colnames(df2))
#> [1] 12
nrow(df1)*ncol(df1)
#> [1] 15

100*sum(rownames(df1) %in% rownames(df2)) * sum(colnames(df1) %in% colnames(df2))/(nrow(df1)*ncol(df1))
#> [1] 80

compare_names <- function(x, y){
  100*sum(rownames(x) %in% rownames(y)) * sum(colnames(x) %in% colnames(y))/(nrow(x)*ncol(x))
}

compare_names(df1, df2) 
#> [1] 80

请注意,它并不总是对称的(因为df1并且df3具有不同数量的单元格,因此它们的匹配单元格名称的比例不同):

compare_names(df1, df3) 
#> [1] 26.66667
compare_names(df3, df1) 
#> [1] 22.22222

当然,这里我们只是比较行名和列名,你没有提到你的问题中值的相似性。


至于适用于每种组合,我想到的最简单的是两个 for 循环:

all_df <- setNames(list(df1, df2, df3),
                   c("df1", "df2", "df3"))

mat_similarities <- matrix(NA_real_,
              nrow=length(all_df),
              ncol=length(all_df),
              dimnames = list(names(all_df),
                              names(all_df)))

for(i in names(all_df)){
  for(j in names(all_df)){
    mat_similarities[i,j] <- compare_names(all_df[[i]],
                                           all_df[[j]])
  }
}

round(mat_similarities)
#>     df1 df2 df3
#> df1 100  80  27
#> df2  80 100  27
#> df3  22  22 100

推荐阅读