生成所有可能的对,并在R中计数频率
我有一个产品(苹果、梨、香蕉)的数据框架,这些产品在不同的地点(城市)销售,属于不同的类别(食品和食用品) 我想数一数任何一对产品在任何类别中出现在一起的次数 这是一个示例数据集,我正在尝试使用它:生成所有可能的对,并在R中计数频率,r,dplyr,R,Dplyr,我有一个产品(苹果、梨、香蕉)的数据框架,这些产品在不同的地点(城市)销售,属于不同的类别(食品和食用品) 我想数一数任何一对产品在任何类别中出现在一起的次数 这是一个示例数据集,我正在尝试使用它: category <- c('food','food','food','food','food','food','edibles','edibles','edibles','edibles', 'edibles') location <- c('houston, TX', 'housto
category <- c('food','food','food','food','food','food','edibles','edibles','edibles','edibles', 'edibles')
location <- c('houston, TX', 'houston, TX', 'las vegas, NV', 'las vegas, NV', 'philadelphia, PA', 'philadelphia, PA', 'austin, TX', 'austin, TX', 'charlotte, NC', 'charlotte, NC', 'charlotte, NC')
item <- c('apple', 'banana', 'apple', 'pear', 'apple', 'pear', 'pear', 'apple', 'apple', 'pear', 'banana')
food_data <- data.frame(cbind(category, location, item), stringsAsFactors = FALSE)
category来自tidyverse
的解决方案。其想法是创建食品数据2
,这是食品数据的广泛格式。然后,在每个唯一项目之间创建组合,并使用map2\u int
循环遍历每个项目组合以计算数字。此解决方案适用于任何数量的项目
library(tidyverse)
food_data2 <- food_data %>%
mutate(count = 1) %>%
spread(item, count, fill = 0)
food_combination <- food_data %>%
pull(item) %>%
unique() %>%
combn(2) %>%
t() %>%
as_data_frame() %>%
mutate(count = map2_int(V1, V2,
~sum(apply(food_data2 %>% select(.x, .y), 1, sum) == 2)))
# View the result
food_combination
# A tibble: 3 x 3
V1 V2 count
<chr> <chr> <int>
1 apple banana 2
2 apple pear 4
3 banana pear 1
来自tidyverse
的解决方案。其想法是创建食品数据2
,这是食品数据的广泛格式。然后,在每个唯一项目之间创建组合,并使用map2\u int
循环遍历每个项目组合以计算数字。此解决方案适用于任何数量的项目
library(tidyverse)
food_data2 <- food_data %>%
mutate(count = 1) %>%
spread(item, count, fill = 0)
food_combination <- food_data %>%
pull(item) %>%
unique() %>%
combn(2) %>%
t() %>%
as_data_frame() %>%
mutate(count = map2_int(V1, V2,
~sum(apply(food_data2 %>% select(.x, .y), 1, sum) == 2)))
# View the result
food_combination
# A tibble: 3 x 3
V1 V2 count
<chr> <chr> <int>
1 apple banana 2
2 apple pear 4
3 banana pear 1
下面是使用tidyverse
和crossprod
的一种方法;通过使用spread
,它将来自同一类别位置组合的所有项目/水果转换为一行,项目作为标题(这要求每个类别国家/地区没有重复的项目,否则需要预聚合步骤),值指示存在crossprod
主要计算项目对列的内积,并给出共现数
library(tidyverse)
food_data %>%
mutate(n = 1) %>%
spread(item, n, fill=0) %>%
select(-category, -location) %>%
{crossprod(as.matrix(.))} %>%
`diag<-`(0)
# apple banana pear
#apple 0 2 4
#banana 2 0 1
#pear 4 1 0
下面是使用tidyverse
和crossprod
的一种方法;通过使用spread
,它将来自同一类别位置组合的所有项目/水果转换为一行,项目作为标题(这要求每个类别国家/地区没有重复的项目,否则需要预聚合步骤),值指示存在crossprod
主要计算项目对列的内积,并给出共现数
library(tidyverse)
food_data %>%
mutate(n = 1) %>%
spread(item, n, fill=0) %>%
select(-category, -location) %>%
{crossprod(as.matrix(.))} %>%
`diag<-`(0)
# apple banana pear
#apple 0 2 4
#banana 2 0 1
#pear 4 1 0
这里有一个小函数,可以满足您的需要。它可以通过dplyr::
评估系统推广到任意分组列。可能是更好的方法,但这是有效的:p
评论/解释是内联的~~
library("dplyr")
# a function to apply to `food_data` from the original post
count_combos <- function(df, group_col1, group_col2, count_col){
# use `combn()` to get all the unique pairs from the `$items` col
combos <- t(combn(sort(unique(df[[count_col]])), 2)) %>%
as_data_frame() %>%
# initialize an empty column to catch the counts
mutate(count=NA)
# create a new df from the colnames passed as args,
# (it would be more general to just use the dplyr evaluation system (@_@))
df <- data_frame(
group_col1 = df[[group_col1]],
group_col2 = df[[group_col2]],
count_col = df[[count_col]]
)
# for each combo of the grouping vars, get a pipe-seperated string of items
df <- df %>%
group_by(group_col1, group_col2) %>% summarize(
items = paste(unique(count_col), collapse="|")
) %>% ungroup()
# for each item pair/combo, get the number of rows of `df` with both items
combos$count <- sapply(1:nrow(combos), function(x){
sum(grepl(combos$V1[x], df$items) & grepl(combos$V2[x], df$items))
})
# and return it in a nice df
return(combos)
}
# apply the function
count_combos(food_data,
group_col1="category", group_col2="location", count_col="item")
库(“dplyr”)
#一个应用于原始帖子中“food_data”的函数
计数\u组合%
#初始化空列以捕获计数
变异(计数=NA)
#从作为args传递的colnames创建新的df,
#(更一般的做法是只使用dplyr评估系统)
df%汇总(
项目=粘贴(唯一(计数列),折叠=“|”)
)%%>%ungroup()
#对于每个项目对/组合,获取两个项目的“df”行数
combos$count这里有一个小函数,可以满足您的需要。它可以通过dplyr::
评估系统推广到任意分组列。可能是更好的方法,但这是有效的:p
评论/解释是内联的~~
library("dplyr")
# a function to apply to `food_data` from the original post
count_combos <- function(df, group_col1, group_col2, count_col){
# use `combn()` to get all the unique pairs from the `$items` col
combos <- t(combn(sort(unique(df[[count_col]])), 2)) %>%
as_data_frame() %>%
# initialize an empty column to catch the counts
mutate(count=NA)
# create a new df from the colnames passed as args,
# (it would be more general to just use the dplyr evaluation system (@_@))
df <- data_frame(
group_col1 = df[[group_col1]],
group_col2 = df[[group_col2]],
count_col = df[[count_col]]
)
# for each combo of the grouping vars, get a pipe-seperated string of items
df <- df %>%
group_by(group_col1, group_col2) %>% summarize(
items = paste(unique(count_col), collapse="|")
) %>% ungroup()
# for each item pair/combo, get the number of rows of `df` with both items
combos$count <- sapply(1:nrow(combos), function(x){
sum(grepl(combos$V1[x], df$items) & grepl(combos$V2[x], df$items))
})
# and return it in a nice df
return(combos)
}
# apply the function
count_combos(food_data,
group_col1="category", group_col2="location", count_col="item")
库(“dplyr”)
#一个应用于原始帖子中“food_data”的函数
计数\u组合%
#初始化空列以捕获计数
变异(计数=NA)
#从作为args传递的colnames创建新的df,
#(更一般的做法是只使用dplyr评估系统)
df%汇总(
项目=粘贴(唯一(计数列),折叠=“|”)
)%%>%ungroup()
#对于每个项目对/组合,获取两个项目的“df”行数
combos$count在我的真实数据集中,我有数百个不同的项目,所以我无法像这样手动生成对名称:/@HarryM谢谢你的评论。我已更新了我的答案,该答案适用于任何数量的项目,而无需手动指定列名。在我的真实数据集中,我有数百个不同的项目,因此我无法像下面这样手动生成对名称:/@HarryM感谢您的评论。我已经更新了我的答案,它应该适用于任何数量的项目,而无需手动指定列名。这看起来非常整洁!在我的实际数据集中,我有数百个不同的项目。有没有一种简单的方法可以将这个矩阵折叠成一个数据帧,其中第一列是数据对的名称,第二列是该数据对的计数?如果您不关心按交换顺序复制的数据对,可以将%%>%as.data.frame.table()链接起来
仅将矩阵转换为数据帧。我想输出像第1行:苹果,香蕉,2;第二排:苹果,梨,4我一开始搞错了。它应该是as.data.frame.table
而不是as.data.frame
。这看起来非常整洁!在我的实际数据集中,我有数百个不同的项目。有没有一种简单的方法可以将这个矩阵折叠成一个数据帧,其中第一列是数据对的名称,第二列是该数据对的计数?如果您不关心按交换顺序复制的数据对,可以将%%>%as.data.frame.table()链接起来
仅将矩阵转换为数据帧。我想输出像第1行:苹果,香蕉,2;第二排:苹果,梨,4我一开始搞错了。它应该是as.data.frame.table
而不是as.data.frame
。避免所有重塑可以简化为crossprod(table(food_data[-1])
。然后,如果需要,您可以使用diag
将对角线设置为零。重新规划所有形状可以简化为crossprod(表(食品数据[-1])
。然后,如果需要,可以使用diag
将对角线设置为零