在 R 中查找行对的组合总和
Finding combined sums of pairs of rows in R
我有一个包含测试结果的数据框(行是玩家;列 Q1 ... Q6 是不同的问题)。现在我想找出哪对球员的总得分最高:
# Generating sample data.
n = 6
set.seed(1986)
results_df = data.frame(Player = c("A", "B", "C", "D", "E", "F"),
Q1 = sample(0:1, size = n, replace = TRUE),
Q2 = sample(0:1, size = n, replace = TRUE),
Q3 = sample(0:1, size = n, replace = TRUE),
Q4 = sample(0:1, size = n, replace = TRUE),
Q5 = sample(0:1, size = n, replace = TRUE),
Q6 = sample(0:1, size = n , replace = TRUE))
head(results_df)
Player Q1 Q2 Q3 Q4 Q5 Q6
1 A 1 0 1 0 0 0
2 B 1 1 0 0 0 0
3 C 0 1 0 1 0 1
4 D 0 1 1 0 1 1
5 E 1 1 1 1 1 1
6 F 1 0 0 1 0 1
1 和 0 是判断每位玩家答对 (1) 还是答错 (0) 问题的假人。现在我想把每一对球员组合起来,看看他们作为一对球员会做得多好。
有谁知道如何将上面的数据框转换成下面这样的东西?
(这里我只是手工总结了每个对的组合:A 有 3 个正确,加上 B 有 3 个正确的问题,A 有错误,将得到 6 个组合,依此类推......)
Player A B C D E F
1 A 2 3 5 5 6 4
2 B 3 2 4 5 6 4
3 C 5 4 3 5 6 4
4 D 5 5 5 4 6 6
5 E 6 6 6 6 6 6
6 F 4 4 4 6 6 3
下面是计算所有玩家综合得分的代码。我不知道,为什么你需要矩阵形式的它们,但使用它你应该能够创建矩阵。解决方案是使用 tidyr::pivot_longer()
然后使用 dplyr.
# Generating sample data.
set.seed(1986)
n <- 6
results_df <- data.frame(
Player = c("A", "B", "C", "D", "E", "F"),
Q1 = sample(0:1, size = n, replace = TRUE),
Q2 = sample(0:1, size = n, replace = TRUE),
Q3 = sample(0:1, size = n, replace = TRUE),
Q4 = sample(0:1, size = n, replace = TRUE),
Q5 = sample(0:1, size = n, replace = TRUE),
Q6 = sample(0:1, size = n, replace = TRUE)
)
results_df
#> Player Q1 Q2 Q3 Q4 Q5 Q6
#> 1 A 1 0 1 0 0 0
#> 2 B 1 1 0 0 0 0
#> 3 C 0 1 0 1 0 1
#> 4 D 0 1 1 0 1 1
#> 5 E 1 1 1 1 1 1
#> 6 F 1 0 0 1 0 1
results_df |>
tidyr::pivot_longer(cols = tidyselect::starts_with("Q"), names_to = "question", values_to = "score") |>
dplyr::group_by(Player) |>
dplyr::summarise(total = sum(score))
#> # A tibble: 6 x 2
#> Player total
#> <chr> <int>
#> 1 A 2
#> 2 B 2
#> 3 C 3
#> 4 D 4
#> 5 E 6
#> 6 F 3
由 reprex package (v2.0.1)
于 2022-02-04 创建
在基础 R 中你可以这样做:
a <- data.frame(t(as.matrix(results_df[-1])))
b <- combn(a, 2, function(x)sum(x[1] | x[2]))
attributes(b) <- list(Size = ncol(a), Labels = results_df$Player)
d <- as.matrix(structure(b, class = 'dist'))
diag(d) <- colSums(a)
d
A B C D E F
A 2 3 5 5 6 4
B 3 2 4 5 6 4
C 5 4 3 5 6 4
D 5 5 5 4 6 6
E 6 6 6 6 6 6
F 4 4 4 6 6 3
你可以用它来计算总和
n <- 6
# get the combinations
ee <- expand.grid(1:n, 1:n)
matrix(rowSums(
results_df[,-1][ee[,1],] | results_df[,-1][ee[,2],]), n,
dimnames = list(results_df[,1], results_df[,1]))
A B C D E F
A 2 3 5 5 6 4
B 3 2 4 5 6 4
C 5 4 3 5 6 4
D 5 5 5 4 6 6
E 6 6 6 6 6 6
F 4 4 4 6 6 3
使用此输入数据:
# Player Q1 Q2 Q3 Q4 Q5 Q6
#1 A 0 1 1 0 1 1
#2 B 0 0 1 0 1 1
#3 C 1 1 0 0 0 0
#4 D 0 1 0 1 1 1
#5 E 1 1 0 1 0 1
#6 F 0 0 0 1 0 1
有一个简单的base
解决方案:
scr <- rowSums(dat[, -1]) # 1)
res <- data.frame(outer(scr, scr, '+') - diag(scr)) # 2)
dimnames(res) <- dat[, c(1, 1)] # 3)
- 计算每一行的分数总和(即
Player
);
- 找出在 (1) 中获得的每对分数之间的总和。从对角线上减去原始分数,例如对于
A
-A
对 (1) 中得到的原始数字,不是它的两倍;
- 设置 row- 和 column-names 为玩家名称;
这给你这个结果:
# A B C D E F
# A 4 7 6 8 8 6
# B 7 3 5 7 7 5
# C 6 5 2 6 6 4
# D 8 7 6 4 8 6
# E 8 7 6 8 4 6
# F 6 5 4 6 6 2
数据:
dat <- structure(
list(
Player = c("A", "B", "C", "D", "E", "F"),
Q1 = c(0, 0, 1, 0, 1, 0),
Q2 = c(1, 0, 1, 1, 1, 0),
Q3 = c(1, 1, 0, 0, 0, 0),
Q4 = c(0, 0, 0, 1, 1, 1),
Q5 = c(1, 1, 0, 1, 0, 0),
Q6 = c(1, 1, 0, 1, 1, 1)
),
row.names = c(NA,-6L),
class = "data.frame"
)
具有 outer
的基础 R 选项
> lst <- asplit(`row.names<-`(as.matrix(results_df[-1]), results_df$Player), 1)
> outer(lst, lst, FUN = Vectorize(function(x, y) sum(x + y > 0)))
A B C D E F
A 2 3 5 5 6 4
B 3 2 4 5 6 4
C 5 4 3 5 6 4
D 5 5 5 4 6 6
E 6 6 6 6 6 6
F 4 4 4 6 6 3
我有一个包含测试结果的数据框(行是玩家;列 Q1 ... Q6 是不同的问题)。现在我想找出哪对球员的总得分最高:
# Generating sample data.
n = 6
set.seed(1986)
results_df = data.frame(Player = c("A", "B", "C", "D", "E", "F"),
Q1 = sample(0:1, size = n, replace = TRUE),
Q2 = sample(0:1, size = n, replace = TRUE),
Q3 = sample(0:1, size = n, replace = TRUE),
Q4 = sample(0:1, size = n, replace = TRUE),
Q5 = sample(0:1, size = n, replace = TRUE),
Q6 = sample(0:1, size = n , replace = TRUE))
head(results_df)
Player Q1 Q2 Q3 Q4 Q5 Q6
1 A 1 0 1 0 0 0
2 B 1 1 0 0 0 0
3 C 0 1 0 1 0 1
4 D 0 1 1 0 1 1
5 E 1 1 1 1 1 1
6 F 1 0 0 1 0 1
1 和 0 是判断每位玩家答对 (1) 还是答错 (0) 问题的假人。现在我想把每一对球员组合起来,看看他们作为一对球员会做得多好。
有谁知道如何将上面的数据框转换成下面这样的东西?
(这里我只是手工总结了每个对的组合:A 有 3 个正确,加上 B 有 3 个正确的问题,A 有错误,将得到 6 个组合,依此类推......)
Player A B C D E F
1 A 2 3 5 5 6 4
2 B 3 2 4 5 6 4
3 C 5 4 3 5 6 4
4 D 5 5 5 4 6 6
5 E 6 6 6 6 6 6
6 F 4 4 4 6 6 3
下面是计算所有玩家综合得分的代码。我不知道,为什么你需要矩阵形式的它们,但使用它你应该能够创建矩阵。解决方案是使用 tidyr::pivot_longer()
然后使用 dplyr.
# Generating sample data.
set.seed(1986)
n <- 6
results_df <- data.frame(
Player = c("A", "B", "C", "D", "E", "F"),
Q1 = sample(0:1, size = n, replace = TRUE),
Q2 = sample(0:1, size = n, replace = TRUE),
Q3 = sample(0:1, size = n, replace = TRUE),
Q4 = sample(0:1, size = n, replace = TRUE),
Q5 = sample(0:1, size = n, replace = TRUE),
Q6 = sample(0:1, size = n, replace = TRUE)
)
results_df
#> Player Q1 Q2 Q3 Q4 Q5 Q6
#> 1 A 1 0 1 0 0 0
#> 2 B 1 1 0 0 0 0
#> 3 C 0 1 0 1 0 1
#> 4 D 0 1 1 0 1 1
#> 5 E 1 1 1 1 1 1
#> 6 F 1 0 0 1 0 1
results_df |>
tidyr::pivot_longer(cols = tidyselect::starts_with("Q"), names_to = "question", values_to = "score") |>
dplyr::group_by(Player) |>
dplyr::summarise(total = sum(score))
#> # A tibble: 6 x 2
#> Player total
#> <chr> <int>
#> 1 A 2
#> 2 B 2
#> 3 C 3
#> 4 D 4
#> 5 E 6
#> 6 F 3
由 reprex package (v2.0.1)
于 2022-02-04 创建在基础 R 中你可以这样做:
a <- data.frame(t(as.matrix(results_df[-1])))
b <- combn(a, 2, function(x)sum(x[1] | x[2]))
attributes(b) <- list(Size = ncol(a), Labels = results_df$Player)
d <- as.matrix(structure(b, class = 'dist'))
diag(d) <- colSums(a)
d
A B C D E F
A 2 3 5 5 6 4
B 3 2 4 5 6 4
C 5 4 3 5 6 4
D 5 5 5 4 6 6
E 6 6 6 6 6 6
F 4 4 4 6 6 3
你可以用它来计算总和
n <- 6
# get the combinations
ee <- expand.grid(1:n, 1:n)
matrix(rowSums(
results_df[,-1][ee[,1],] | results_df[,-1][ee[,2],]), n,
dimnames = list(results_df[,1], results_df[,1]))
A B C D E F
A 2 3 5 5 6 4
B 3 2 4 5 6 4
C 5 4 3 5 6 4
D 5 5 5 4 6 6
E 6 6 6 6 6 6
F 4 4 4 6 6 3
使用此输入数据:
# Player Q1 Q2 Q3 Q4 Q5 Q6
#1 A 0 1 1 0 1 1
#2 B 0 0 1 0 1 1
#3 C 1 1 0 0 0 0
#4 D 0 1 0 1 1 1
#5 E 1 1 0 1 0 1
#6 F 0 0 0 1 0 1
有一个简单的base
解决方案:
scr <- rowSums(dat[, -1]) # 1)
res <- data.frame(outer(scr, scr, '+') - diag(scr)) # 2)
dimnames(res) <- dat[, c(1, 1)] # 3)
- 计算每一行的分数总和(即
Player
); - 找出在 (1) 中获得的每对分数之间的总和。从对角线上减去原始分数,例如对于
A
-A
对 (1) 中得到的原始数字,不是它的两倍; - 设置 row- 和 column-names 为玩家名称;
这给你这个结果:
# A B C D E F
# A 4 7 6 8 8 6
# B 7 3 5 7 7 5
# C 6 5 2 6 6 4
# D 8 7 6 4 8 6
# E 8 7 6 8 4 6
# F 6 5 4 6 6 2
数据:
dat <- structure(
list(
Player = c("A", "B", "C", "D", "E", "F"),
Q1 = c(0, 0, 1, 0, 1, 0),
Q2 = c(1, 0, 1, 1, 1, 0),
Q3 = c(1, 1, 0, 0, 0, 0),
Q4 = c(0, 0, 0, 1, 1, 1),
Q5 = c(1, 1, 0, 1, 0, 0),
Q6 = c(1, 1, 0, 1, 1, 1)
),
row.names = c(NA,-6L),
class = "data.frame"
)
具有 outer
> lst <- asplit(`row.names<-`(as.matrix(results_df[-1]), results_df$Player), 1)
> outer(lst, lst, FUN = Vectorize(function(x, y) sum(x + y > 0)))
A B C D E F
A 2 3 5 5 6 4
B 3 2 4 5 6 4
C 5 4 3 5 6 4
D 5 5 5 4 6 6
E 6 6 6 6 6 6
F 4 4 4 6 6 3