在 R 中计算分类变量的组合,无论顺序如何?

问题描述

感谢您的帮助!我在 R 中有一个包含两列分类变量的数据框,如下所示:

rowA <- c("Square","Circle","Triangle","Square","Triangle")

rowB <- c("Circle","Triangle")

df1 <- data.frame(rowA,rowB)

print(df1)

当我们打印它时,它看起来像这样:

      rowA     rowB
1   Square   Circle
2   Circle   Square
3 Triangle   Square
4   Square   Square
5   Circle   Circle
6 Triangle   Circle
7   Square Triangle
8   Circle Triangle
9 Triangle Triangle

我想计算 rowA 和 rowB 中每个类别组合的频率。这就是我所关心的——组合是可逆的,这意味着“Square - Circle”与我们的目的“Circle - Square”相同,我们希望它们加在一起。理想的输出如下所示:

Pair             Count
Square - Circle      2
Square - Triangle    2
Square - Square      1
Circle - Triangle    2
Circle - Circle      1
Triangle - Triangle  1

如果有人有任何建议,我会很高兴,谢谢!

编辑:帖子被标记为重复问题,但我不同意建议的帖子充分回答了我的问题(因此,经过大量挖掘,我首先提出了问题)。非常感谢这里独特而简单的答案。

解决方法

我们可以用pmin/pmaxcount按行重新排列

library(dplyr)
library(stringr)
df1 %>%
     count(Pair = str_c(pmin(rowA,rowB),' - ',pmax(rowA,rowB)),name = "Count")

-输出

             Pair   Count
1     Circle - Circle 1
2     Circle - Square 2
3   Circle - Triangle 2
4     Square - Square 1
5   Square - Triangle 2
6 Triangle - Triangle 1
,

基本的 R 解决方案是

combs <- apply(as.matrix(df1),1,function(x) paste0(sort(x),collapse = " - "))
as.data.frame(table(combs))
#R>                 combs Freq
#R> 1     Circle - Circle    1
#R> 2     Circle - Square    2
#R> 3   Circle - Triangle    2
#R> 4     Square - Square    1
#R> 5   Square - Triangle    2
#R> 6 Triangle - Triangle    1

# in R 4.1.0 or later
as.matrix(df1) |> 
  apply(1,\(x) paste0(sort(x),collapse = " - ")) |>
  table() |> as.data.frame() |> 
  setNames(c("Pair","Count"))
#R>                  Pair Count
#R> 1     Circle - Circle     1
#R> 2     Circle - Square     2
#R> 3   Circle - Triangle     2
#R> 4     Square - Square     1
#R> 5   Square - Triangle     2
#R> 6 Triangle - Triangle     1
,

另一种使用图形的方法

library(igraph)
library(magrittr)
df1 %>% 
  graph_from_data_frame(directed = FALSE) %>%
  as_adjacency_matrix() 
#          Square Circle Triangle
# Square        1      2        2
# Circle        2      1        2
# Triangle      2      2        1