如何识别组内最常见的值组合?

问题描述 投票:0回答:3

我有一个表,其中每一行代表一名学生在一门课程中的注册情况,与此类似,但要大得多:

学生 课程
001 PSYC101
001 化学102
002 PSYC101
002 SPAN101
002 BIO101
003 BIO101
003 ENG201
003 HIND101
003 化学102
004 PSYC101
004 化学102
004 HIND101

我想知道学生最常一起选修哪些课程组合。我从 2 道菜组合开始,但也可能想看看 3 道菜组合。

我完全不知道这个程序的名称。

我发现这个使用

dplyr
包的类似示例:https://stackoverflow.com/questions/61613192/r-how-to-find-the-most-frequent-combinations

但是,我不认为这正是我想要的。当某些学生修读了 2 门以上课程时,我想要所有可能的 2 门课程组合。例如,对于学生 3,他们将具有以下内容:

  • BIO101 和 ENG201
  • BIO101 & HIND101
  • BIO101 & CHEM102
  • ENG201 和 HIND101
  • ENG201 & CHEM102
  • HIND101 和 CHEM102

然后,我会找到所有学生中最常见的组合。

r combinations
3个回答
6
投票

基本 R 方法使用学生的

combn
(选择 2 个元素)来创建每个特定学生的所有课程的组合,然后使用
table
来查看这些对在整个群体中出现的频率。

我将把合并后的代码放在下面,然后通过分解它来梳理出之后发生的事情,以便它更容易阅读/理解。

如果您想查看 3 个课程选项,请将

combn(x$Course, 2)
更改为
combn(x$Course, 3)
以选择三个课程的组合。

table(apply(do.call(cbind, lapply(split(df, df$Student), \(x)
                                  combn(x$Course, 2))), 2, \(x) paste(sort(x), collapse = "_")))

输出

# BIO101_CHEM102   BIO101_ENG201  BIO101_HIND101 CHEM102_HIND101  ENG201_CHEM102  ENG201_HIND101 
#               1               1               1               1               1               1 

# HIND101_CHEM102  PSYC101_BIO101 PSYC101_CHEM102 PSYC101_HIND101 PSYC101_SPAN101  SPAN101_BIO101 
#               1               1               2               1               1               1 

首先,用

split
将数据框(
df
)分解为每个学生的列表,然后找到课程组合,然后将组合组合并粘贴在一起,然后制作一个表格:

# Split by student
ll <- split(df, df$Student)

# find combinations of courses
combs_list <- lapply(ll, \(x) combn(unique(x$Course), 2))

# combine it into a matrix
combs_combined <- do.call(cbind, combs_list)

# paste combinations together
apply_combined <- apply(combs_combined, 2, \(x) paste(sort(x), collapse = "_"))

#make a table
table(apply_combined)

注意,如果您希望将其放入数据框中,只需将表格包裹起来即可:

data.frame(tt)

# or to order by frequency:
data.frame(tt)[order(tt, decreasing = TRUE),]

#     apply_combined Freq
# 7  CHEM102_HIND101    2
# 8  CHEM102_PSYC101    2
# 1   BIO101_CHEM102    1
# 2    BIO101_ENG201    1
# 3   BIO101_HIND101    1
# ...

数据

df <- read.table(text = "Student    Course
001 PSYC101
001 CHEM102
002 PSYC101
002 SPAN101
002 BIO101
003 BIO101
003 ENG201
003 HIND101
003 CHEM102
004 PSYC101
004 CHEM102
004 HIND101", header = TRUE)

4
投票

您可以过滤掉行数少于感兴趣的

m
组合的学生,使用
combn()
生成组合,然后将其转置并进行行排序,解压小标题,统计结果,然后降序排序。

library(dplyr)
library(tidyr)

n <- 2

dat %>%
  filter(n() >= n, .by = Student) %>%
  reframe(x = t(combn(Course, n)) %>%
            {matrix(.[order(row(.), .)], ncol = ncol(.), byrow = TRUE)} %>%
            as_tibble(), .by = Student) |>
  unpack(x) |>
  count(across(-Student)) |>
  arrange(-n)

# A tibble: 11 × 3
   V1      V2          n
   <chr>   <chr>   <int>
 1 CHEM102 HIND101     2
 2 CHEM102 PSYC101     2
 3 BIO101  CHEM102     1
 4 BIO101  ENG201      1
 5 BIO101  HIND101     1
 6 BIO101  PSYC101     1
 7 BIO101  SPAN101     1
 8 CHEM102 ENG201      1
 9 ENG201  HIND101     1
10 HIND101 PSYC101     1
11 PSYC101 SPAN101     1

对于

n = 3
,您将得到:

# A tibble: 6 × 4
  V1      V2      V3          n
  <chr>   <chr>   <chr>   <int>
1 BIO101  CHEM102 ENG201      1
2 BIO101  CHEM102 HIND101     1
3 BIO101  ENG201  HIND101     1
4 BIO101  PSYC101 SPAN101     1
5 CHEM102 ENG201  HIND101     1
6 CHEM102 HIND101 PSYC101     1

3
投票

另一种

dplyr
方法与
combn

library(dplyr)
df |> 
  arrange(Student, Course) |> 
  reframe(Course_comb = combn(seq_along(Student), 2, function(i) paste(Course[i], collapse = " & ")), .by = Student) |> 
  count(Course_comb, sort = TRUE)

#          Course_comb n
# 1  CHEM102 & PSYC101 2
# 2  CHEM102 & HIND101 2
# 3   BIO101 & PSYC101 1
# 4   BIO101 & SPAN101 1
# 5  PSYC101 & SPAN101 1
# 6   BIO101 & CHEM102 1
# 7    BIO101 & ENG201 1
# 8   BIO101 & HIND101 1
# 9   CHEM102 & ENG201 1
# 10  ENG201 & HIND101 1
# 11 HIND101 & PSYC101 1
© www.soinside.com 2019 - 2024. All rights reserved.