问题描述
我正在尝试计算有多少人从事不同的运动组合。我知道如何计算和绘制相关性,但是我想获得每个合并组中有多少人的实际人数。
这是我的数据的简化演示。 1
表示给定的人从事这项运动,而0
表示不参加该运动。
sports_example <- tibble(
name = c(
"Scarlett","Heather","Sarah","Anna","emma","Charlotte","Cheryl"
),hockey = c(1L,1L,0L,1L),basketball = c(0L,0L),track = c(1L,football = c(0L,0L)
)
使用下面的代码,我可以计算不同运动之间的相关性。我可以说,曲棍球在篮球方面的参与人数多于足球。但是我想计算有多少运动员打曲棍球和篮球(本例中为3)。有简单的算法来计算重叠吗?我的真实数据集包含数十列,因此我的一次性代码无法删除(例如nrow(filter(sports_example,hockey + basketball == 2))
)。
sports_example %>%
select(-name) %>%
cor() %>%
corrgram::corrgram(upper.panel = NULL)
解决方法
我建议您使用下一种方法来确定所有玩家的情况:
library(reshape2)
library(tibble)
library(dplyr)
#Data
sports_example <- tibble(
name = c(
"Scarlett","Heather","Sarah","Anna","Emma","Charlotte","Cheryl"
),hockey = c(1L,1L,0L,1L),basketball = c(0L,0L),track = c(1L,football = c(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
然后,您还可以识别玩家和想要的号码。
,如果您追求成对结果,则可以堆叠数据并使用crossprod()
:
spex <- subset(cbind(sports_example[1],stack(sports_example[-1])),values == 1)
res <- crossprod(table(spex$name,spex$ind))
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
,
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,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