我正在尝试计算有多少人参加不同的运动组合。我知道如何计算和绘制相关性,但我想获得每个组合组中有多少人的实际数字。
这是我的数据的简化演示。
1
表示特定的人从事特定的运动,0
表示她不从事特定的运动。
sports_example <- tibble(
name = c(
"Scarlett",
"Heather",
"Sarah",
"Anna",
"Emma",
"Charlotte",
"Cheryl"
),
hockey = c(1L, 1L, 1L, 1L, 0L, 1L, 1L),
basketball = c(0L, 1L, 1L, 0L, 1L, 1L, 0L),
track = c(1L, 1L, 1L, 0L, 1L, 0L, 1L),
football = c(0L, 1L, 0L, 0L, 0L, 0L, 0L)
)
使用下面的代码,我可以计算不同运动之间的相关性。我可以看出,曲棍球与篮球的共同球员比足球更多。但我想计算有多少运动员同时打曲棍球和篮球(本例中为 3 名)。有没有一种简单的算法来计算重叠?我的真实数据集有几十列,因此我的一次性代码无法删除它(例如
nrow(filter(sports_example, hockey + basketball == 2))
)。
sports_example %>%
select(-name) %>%
cor() %>%
corrgram::corrgram(upper.panel = NULL)
对于成对结果,您可以计算二元变量的矩阵叉积,然后将上三角形和对角线设置为零,以便我们可以过滤以仅保留唯一的对。
res <- crossprod(as.matrix(sports_example[-1]))
res[upper.tri(res, diag = TRUE)] <- 0
subset(as.data.frame.table(res), Freq > 0)
Var1 Var2 Freq
2 basketball hockey 3
3 track hockey 4
4 football hockey 1
7 track basketball 3
8 football basketball 1
12 football track 1
我建议您采用下一种方法,您可以确定所有玩家会发生什么:
library(reshape2)
library(tibble)
library(dplyr)
#Data
sports_example <- tibble(
name = c(
"Scarlett",
"Heather",
"Sarah",
"Anna",
"Emma",
"Charlotte",
"Cheryl"
),
hockey = c(1L, 1L, 1L, 1L, 0L, 1L, 1L),
basketball = c(0L, 1L, 1L, 0L, 1L, 1L, 0L),
track = c(1L, 1L, 1L, 0L, 1L, 0L, 1L),
football = c(0L, 1L, 0L, 0L, 0L, 0L, 0L)
)
#Reshape
Melted <- melt(sports_example,id.vars = 'name')
重塑后,您可以使用
dplyr
函数进行分组和聚合:
#Now filter and compute
Melted %>% group_by(name) %>% filter(variable %in% c('hockey','basketball')) %>%
summarise(N=sum(value))
这将导致:
# A tibble: 7 x 2
name N
<chr> <int>
1 Anna 1
2 Charlotte 2
3 Cheryl 1
4 Emma 1
5 Heather 2
6 Sarah 2
7 Scarlett 1
然后你可以添加一个新的过滤器来达到你想要的:
#Now filter and compute 2
Melted %>% group_by(name) %>% filter(variable %in% c('hockey','basketball')) %>%
summarise(N=sum(value)) %>% filter(N==2)
输出:
# A tibble: 3 x 2
name N
<chr> <int>
1 Charlotte 2
2 Heather 2
3 Sarah 2
然后,您还可以识别玩家和您想要的号码。
怎么样
count()
?
count(sports_example, hockey, basketball)
## hockey basketball n
## <int> <int> <int>
## 1 0 1 1
## 2 1 0 3
## 3 1 1 3
或者
(count(sports_example, hockey, basketball)
%>% filter(hockey==1, basketball==1)
%>% pull(n)
)
base-R 版本会是这样的
with(sports_example, as.data.frame(table(hockey,basketball)))
以长格式获取数据,仅保留
value = 1
的行,为每个name
和count
创建配对组合。
library(dplyr)
sports_example %>%
tidyr::pivot_longer(cols = -name, names_to = 'col') %>%
filter(value == 1) %>%
group_by(name) %>%
summarise(val = if(n() > 1) combn(col, 2, function(x)
sort(toString(x))) else col) %>%
ungroup %>%
count(val)
# val n
# <chr> <int>
#1 basketball, football 1
#2 basketball, track 3
#3 hockey 1
#4 hockey, basketball 3
#5 hockey, football 1
#6 hockey, track 4
#7 track, football 1
此答案适用于
dplyr
> 1.0.0,它允许在 summarise
中返回多行。
您可以矢量化:
(sports_example$hockey & sports_example$basketball) %>% sum