计算数据框 r 中值的共现次数
count co-occurrences of values in dataframe r
我有一个示例数据框如下,我需要探索 Category 列。
> df
Id Category
1 [1,2,3,4]
2 [2,3,5]
3 [1,4,5]
4 [1,2,5]
5 [4]
6 [2,3,5]
7 [1,5]
实际上,数据框中有数千行类别介于 1 到 25 之间。我想看看这些类别在该列中共同出现了多少次。输出应为矩阵或数据框。
矩阵输出:
[,1] [,2] [,3] [,4] [,5]
[1,] 0 2 1 2 3
[2,] 2 0 3 1 3
[3,] 1 3 0 1 2
[4,] 2 1 1 0 1
[5,] 3 3 2 1 0
数据帧输出:
C1 C2 Count
1 2 2
1 3 1
1 4 2
1 5 3
2 3 3
2 4 1
2 5 3
3 4 1
3 5 2
4 5 1
有人可以在这方面帮助我吗?
在用 strsplit
拆分 'Category' 列后,我们可以将 crossprod
与 table
一起使用(仅使用 base R
函数)
out <- crossprod(table(subset(stack(setNames(lapply(strsplit(df$Category,
"[][]|,\s*"), trimws), df$Id))[2:1], nzchar(values))))
diag(out) <- 0
-输出
> out
values
values 1 2 3 4 5
1 0 2 1 2 3
2 2 0 3 1 3
3 1 3 0 1 2
4 2 1 1 0 1
5 3 3 2 1 0
在上面的代码中,我们通过在 strsplit
中拆分 ,
和 []
来提取数字部分,将返回的 list
的名称设置为 Id
列,stack
named
list
到两列 data.frame (stack
),使用 table
得到频率计数然后在 table
输出上用 crossprod
换行。然后 diag
onals 被替换为 0
如果我们需要长格式 data.frame,则 replace
三角矩阵之一为 0,然后转换为 table
并在用 [ 包装后 subset
ing =35=]
out2 <- subset(as.data.frame.table(replace(out, upper.tri(out),
0)), Freq != 0)
row.names(out2) <- NULL
colnames(out2) <- c("C1", "C2", "Count")
-输出
> out2
C1 C2 Count
1 2 1 2
2 3 1 1
3 4 1 2
4 5 1 3
5 3 2 3
6 4 2 1
7 5 2 3
8 4 3 1
9 5 3 2
10 5 4 1
数据
df <- structure(list(Id = 1:7, Category = c("[1,2,3,4]", "[2,3,5]",
"[1,4,5]", "[1,2,5]", "[4]", "[2,3,5]", "[1,5]")),
class = "data.frame", row.names = c(NA,
-7L))
另一个选项:
df %>%
group_by(Id) %>%
mutate(Category = list(reticulate::py_eval(Category))) %>%
unnest(Category) %>%
table() %>%
crossprod() %>%
as.data.frame.table() %>%
filter(Category!=Category.1)
Category Category.1 Freq
1 2 1 2
2 3 1 1
3 4 1 2
4 5 1 3
5 1 2 2
6 3 2 3
7 4 2 1
8 5 2 3
9 1 3 1
10 2 3 3
11 4 3 1
12 5 3 2
13 1 4 2
14 2 4 1
15 3 4 1
16 5 4 1
17 1 5 3
18 2 5 3
19 3 5 2
20 4 5 1
我有一个示例数据框如下,我需要探索 Category 列。
> df
Id Category
1 [1,2,3,4]
2 [2,3,5]
3 [1,4,5]
4 [1,2,5]
5 [4]
6 [2,3,5]
7 [1,5]
实际上,数据框中有数千行类别介于 1 到 25 之间。我想看看这些类别在该列中共同出现了多少次。输出应为矩阵或数据框。
矩阵输出:
[,1] [,2] [,3] [,4] [,5]
[1,] 0 2 1 2 3
[2,] 2 0 3 1 3
[3,] 1 3 0 1 2
[4,] 2 1 1 0 1
[5,] 3 3 2 1 0
数据帧输出:
C1 C2 Count
1 2 2
1 3 1
1 4 2
1 5 3
2 3 3
2 4 1
2 5 3
3 4 1
3 5 2
4 5 1
有人可以在这方面帮助我吗?
在用 strsplit
拆分 'Category' 列后,我们可以将 crossprod
与 table
一起使用(仅使用 base R
函数)
out <- crossprod(table(subset(stack(setNames(lapply(strsplit(df$Category,
"[][]|,\s*"), trimws), df$Id))[2:1], nzchar(values))))
diag(out) <- 0
-输出
> out
values
values 1 2 3 4 5
1 0 2 1 2 3
2 2 0 3 1 3
3 1 3 0 1 2
4 2 1 1 0 1
5 3 3 2 1 0
在上面的代码中,我们通过在 strsplit
中拆分 ,
和 []
来提取数字部分,将返回的 list
的名称设置为 Id
列,stack
named
list
到两列 data.frame (stack
),使用 table
得到频率计数然后在 table
输出上用 crossprod
换行。然后 diag
onals 被替换为 0
如果我们需要长格式 data.frame,则 replace
三角矩阵之一为 0,然后转换为 table
并在用 [ 包装后 subset
ing =35=]
out2 <- subset(as.data.frame.table(replace(out, upper.tri(out),
0)), Freq != 0)
row.names(out2) <- NULL
colnames(out2) <- c("C1", "C2", "Count")
-输出
> out2
C1 C2 Count
1 2 1 2
2 3 1 1
3 4 1 2
4 5 1 3
5 3 2 3
6 4 2 1
7 5 2 3
8 4 3 1
9 5 3 2
10 5 4 1
数据
df <- structure(list(Id = 1:7, Category = c("[1,2,3,4]", "[2,3,5]",
"[1,4,5]", "[1,2,5]", "[4]", "[2,3,5]", "[1,5]")),
class = "data.frame", row.names = c(NA,
-7L))
另一个选项:
df %>%
group_by(Id) %>%
mutate(Category = list(reticulate::py_eval(Category))) %>%
unnest(Category) %>%
table() %>%
crossprod() %>%
as.data.frame.table() %>%
filter(Category!=Category.1)
Category Category.1 Freq
1 2 1 2
2 3 1 1
3 4 1 2
4 5 1 3
5 1 2 2
6 3 2 3
7 4 2 1
8 5 2 3
9 1 3 1
10 2 3 3
11 4 3 1
12 5 3 2
13 1 4 2
14 2 4 1
15 3 4 1
16 5 4 1
17 1 5 3
18 2 5 3
19 3 5 2
20 4 5 1