观察结果在 R 行中一起出现的频率
How often observations occur together in rows R
我有一个与下面的数据框相当的数据框:
V1 V2 V3 V4 V5 V6 V7
A B C D NA NA NA
A E F NA NA NA NA
D A C B F E NA
A E NA NA NA NA NA
每一行都是一个病人,数据框中的每个字母代表一个特定的诊断。
我想了解特定诊断一起出现的频率,
例如诊断 A 与诊断 E 按行发生了多少次? (三次)。
I am hoping to produce a matrix like this:
A B C D E F
A 0 2 2 2 3 2
B 2 0 2
C 2 2 0 etc etc
D 2
E 3
F 2
(I have not completely filled it out)
它本质上是一个邻接矩阵,除了观察值不需要直接相邻,它们只需要在同一行即可。
从这里我会制作一个和弦图。
感谢您的帮助!
我认为手工构建它会很有趣。该算法非常简单。对于每个患者,找到同时发生的诊断并将其写入上三角矩阵。
set.seed(357)
xy <- matrix(sample(LETTERS[1:15], size = 80, replace = TRUE), nrow = 8)
> head(xy)
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] "G" "F" "M" "N" "D" "G" "N" "H" "K" "K"
[2,] "H" "I" "C" "K" "H" "E" "H" "E" "I" "G"
[3,] "G" "C" "C" "L" "N" "F" "M" "K" "C" "E"
[4,] "A" "K" "G" "O" "I" "C" "C" "B" "O" "I"
[5,] "K" "O" "E" "B" "M" "O" "F" "C" "L" "N"
[6,] "D" "H" "K" "H" "I" "N" "B" "F" "A" "H"
# Find all unique diagnoses.
all.diagnoses <- unique(as.vector(xy))
all.diagnoses <- sort(as.character(all.diagnoses))
# This is a way of creating an empty matrix.
out <- matrix(rep(NA, length(all.diagnoses)^2), nrow = length(all.diagnoses),
dimnames = list(all.diagnoses, all.diagnoses))
for (i in 1:nrow(xy)) {
combinations <- combn(unique(xy[i, ]), m = 2, simplify = FALSE)
for (j in 1:length(combinations)) {
# Add occurrence of each combination to the corresponding combination.
com <- sort(combinations[[j]])
out[com[1], com[2]] <- sum(out[com[1], com[2]], 1, na.rm = TRUE)
}
}
> out
A B C D E F G H I J K L M N O
A NA 2 1 2 NA 1 1 1 2 1 3 1 1 2 2
B NA NA 2 1 1 2 1 1 2 NA 3 1 1 2 2
C NA NA NA NA 3 2 3 1 2 NA 4 2 2 2 2
D NA NA NA NA NA 2 1 3 2 2 3 1 3 4 2
E NA NA NA NA NA 2 2 1 1 NA 3 2 2 2 1
F NA NA NA NA NA NA 2 2 1 NA 4 2 3 4 1
G NA NA NA NA NA NA NA 2 2 NA 4 1 2 2 1
H NA NA NA NA NA NA NA NA 3 1 3 NA 2 3 1
I NA NA NA NA NA NA NA NA NA 1 3 NA 1 2 2
J NA NA NA NA NA NA NA NA NA NA 1 1 2 2 2
K NA NA NA NA NA NA NA NA NA NA NA 3 4 5 3
L NA NA NA NA NA NA NA NA NA NA NA NA 3 3 2
M NA NA NA NA NA NA NA NA NA NA NA NA NA 5 3
N NA NA NA NA NA NA NA NA NA NA NA NA NA NA 3
O NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
这是另一种方法,它使用 自连接 为每位患者创建可能的诊断组合:
library(data.table)
library(magrittr)
co_occ_mat <- function(DT) {
DT[, id := .I] %>%
melt("id", na.rm = TRUE, value.name = "diagnosis") %>%
unique(by = c("id", "diagnosis")) %>%
.[., on = .(id), allow.cartesian = TRUE] %>%
.[diagnosis != i.diagnosis] %>%
dcast(diagnosis ~ i.diagnosis, length)
}
有了OP的样本数据,co_occ_mat()
returns
fread("V1 V2 V3 V4 V5 V6 V7
A B C D NA NA NA
A E F NA NA NA NA
D A C B F E NA
A E NA NA NA NA NA") %>%
co_occ_mat()
diagnosis A B C D E F
1: A 0 2 2 2 3 2
2: B 2 0 2 2 1 1
3: C 2 2 0 2 1 1
4: D 2 2 2 0 1 1
5: E 3 1 1 1 0 2
6: F 2 1 1 1 2 0
符合OP的预期结果。
co_occ_mat()
中的步骤是:
- 为每一行添加一个
id
列,即 patient
- 重塑为长格式
- 删除任何重复项,以防对一位患者的诊断报告不止一次
- 通过笛卡尔自连接为每个
id
创建诊断对
- 删除两个诊断相同的对的琐碎案例
- 通过重塑为宽格式并计算患者数量来创建共现矩阵
使用来自
的数据
RNGversion("3.6.0")
set.seed(357)
matrix(sample(LETTERS[1:15], size = 80, replace = TRUE), nrow = 8) %>%
as.data.table() %T>% print() %>%
co_occ_mat()
V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
1: G F M N D G N H K K
2: H I C K H E H E I G
3: G C C L N F M K C E
4: A K G O I C C B O I
5: K O E B M O F C L N
6: D H K H I N B F A H
7: J N D J L K M A O O
8: J D I M O H N O H H
我们得到
diagnosis A B C D E F G H I J K L M N O
1: A 0 2 1 2 0 1 1 1 2 1 3 1 1 2 2
2: B 2 0 2 1 1 2 1 1 2 0 3 1 1 2 2
3: C 1 2 0 0 3 2 3 1 2 0 4 2 2 2 2
4: D 2 1 0 0 0 2 1 3 2 2 3 1 3 4 2
5: E 0 1 3 0 0 2 2 1 1 0 3 2 2 2 1
6: F 1 2 2 2 2 0 2 2 1 0 4 2 3 4 1
7: G 1 1 3 1 2 2 0 2 2 0 4 1 2 2 1
8: H 1 1 1 3 1 2 2 0 3 1 3 0 2 3 1
9: I 2 2 2 2 1 1 2 3 0 1 3 0 1 2 2
10: J 1 0 0 2 0 0 0 1 1 0 1 1 2 2 2
11: K 3 3 4 3 3 4 4 3 3 1 0 3 4 5 3
12: L 1 1 2 1 2 2 1 0 0 1 3 0 3 3 2
13: M 1 1 2 3 2 3 2 2 1 2 4 3 0 5 3
14: N 2 2 2 4 2 4 2 3 2 2 5 3 5 0 3
15: O 2 2 2 2 1 1 1 1 2 2 3 2 3 3 0
出于某种我还不明白的原因,需要在 set.seed(357)
之前调用 RNGversion("3.6.0")
才能重现 Roman 的随机数。
请注意,此测试用例包含每个患者的重复诊断,例如,第 1 行中的 K
。
这是另一个使用 table
的基本 R 选项:
pairs <- as.data.frame(do.call(rbind,
apply(dat, 1L, function(x) t(combn(na.omit(x), 2L)))))
tab <- table(pairs)
ut <- tab
ut[lower.tri(tab)] <- 0L
lt <- tab
lt[upper.tri(tab)] <- 0L
ans <- t(lt) + ut
ans + t(ans)
输出:
V1
V2 A B C D E F
A 0 2 2 2 3 2
B 2 0 2 2 1 1
C 2 2 0 2 1 1
D 2 2 2 0 1 1
E 3 1 1 1 0 2
F 2 1 1 1 2 0
数据:
dat <- read.table(text="V1 V2 V3 V4 V5 V6 V7
A B C D NA NA NA
A E F NA NA NA NA
D A C B 'F' E NA
A E NA NA NA NA NA", header=TRUE, colClasses="character")
我有一个与下面的数据框相当的数据框:
V1 V2 V3 V4 V5 V6 V7
A B C D NA NA NA
A E F NA NA NA NA
D A C B F E NA
A E NA NA NA NA NA
每一行都是一个病人,数据框中的每个字母代表一个特定的诊断。
我想了解特定诊断一起出现的频率, 例如诊断 A 与诊断 E 按行发生了多少次? (三次)。
I am hoping to produce a matrix like this:
A B C D E F
A 0 2 2 2 3 2
B 2 0 2
C 2 2 0 etc etc
D 2
E 3
F 2
(I have not completely filled it out)
它本质上是一个邻接矩阵,除了观察值不需要直接相邻,它们只需要在同一行即可。
从这里我会制作一个和弦图。
感谢您的帮助!
我认为手工构建它会很有趣。该算法非常简单。对于每个患者,找到同时发生的诊断并将其写入上三角矩阵。
set.seed(357)
xy <- matrix(sample(LETTERS[1:15], size = 80, replace = TRUE), nrow = 8)
> head(xy)
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] "G" "F" "M" "N" "D" "G" "N" "H" "K" "K"
[2,] "H" "I" "C" "K" "H" "E" "H" "E" "I" "G"
[3,] "G" "C" "C" "L" "N" "F" "M" "K" "C" "E"
[4,] "A" "K" "G" "O" "I" "C" "C" "B" "O" "I"
[5,] "K" "O" "E" "B" "M" "O" "F" "C" "L" "N"
[6,] "D" "H" "K" "H" "I" "N" "B" "F" "A" "H"
# Find all unique diagnoses.
all.diagnoses <- unique(as.vector(xy))
all.diagnoses <- sort(as.character(all.diagnoses))
# This is a way of creating an empty matrix.
out <- matrix(rep(NA, length(all.diagnoses)^2), nrow = length(all.diagnoses),
dimnames = list(all.diagnoses, all.diagnoses))
for (i in 1:nrow(xy)) {
combinations <- combn(unique(xy[i, ]), m = 2, simplify = FALSE)
for (j in 1:length(combinations)) {
# Add occurrence of each combination to the corresponding combination.
com <- sort(combinations[[j]])
out[com[1], com[2]] <- sum(out[com[1], com[2]], 1, na.rm = TRUE)
}
}
> out
A B C D E F G H I J K L M N O
A NA 2 1 2 NA 1 1 1 2 1 3 1 1 2 2
B NA NA 2 1 1 2 1 1 2 NA 3 1 1 2 2
C NA NA NA NA 3 2 3 1 2 NA 4 2 2 2 2
D NA NA NA NA NA 2 1 3 2 2 3 1 3 4 2
E NA NA NA NA NA 2 2 1 1 NA 3 2 2 2 1
F NA NA NA NA NA NA 2 2 1 NA 4 2 3 4 1
G NA NA NA NA NA NA NA 2 2 NA 4 1 2 2 1
H NA NA NA NA NA NA NA NA 3 1 3 NA 2 3 1
I NA NA NA NA NA NA NA NA NA 1 3 NA 1 2 2
J NA NA NA NA NA NA NA NA NA NA 1 1 2 2 2
K NA NA NA NA NA NA NA NA NA NA NA 3 4 5 3
L NA NA NA NA NA NA NA NA NA NA NA NA 3 3 2
M NA NA NA NA NA NA NA NA NA NA NA NA NA 5 3
N NA NA NA NA NA NA NA NA NA NA NA NA NA NA 3
O NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
这是另一种方法,它使用 自连接 为每位患者创建可能的诊断组合:
library(data.table)
library(magrittr)
co_occ_mat <- function(DT) {
DT[, id := .I] %>%
melt("id", na.rm = TRUE, value.name = "diagnosis") %>%
unique(by = c("id", "diagnosis")) %>%
.[., on = .(id), allow.cartesian = TRUE] %>%
.[diagnosis != i.diagnosis] %>%
dcast(diagnosis ~ i.diagnosis, length)
}
有了OP的样本数据,co_occ_mat()
returns
fread("V1 V2 V3 V4 V5 V6 V7
A B C D NA NA NA
A E F NA NA NA NA
D A C B F E NA
A E NA NA NA NA NA") %>%
co_occ_mat()
diagnosis A B C D E F 1: A 0 2 2 2 3 2 2: B 2 0 2 2 1 1 3: C 2 2 0 2 1 1 4: D 2 2 2 0 1 1 5: E 3 1 1 1 0 2 6: F 2 1 1 1 2 0
符合OP的预期结果。
co_occ_mat()
中的步骤是:
- 为每一行添加一个
id
列,即 patient - 重塑为长格式
- 删除任何重复项,以防对一位患者的诊断报告不止一次
- 通过笛卡尔自连接为每个
id
创建诊断对
- 删除两个诊断相同的对的琐碎案例
- 通过重塑为宽格式并计算患者数量来创建共现矩阵
使用来自
RNGversion("3.6.0")
set.seed(357)
matrix(sample(LETTERS[1:15], size = 80, replace = TRUE), nrow = 8) %>%
as.data.table() %T>% print() %>%
co_occ_mat()
V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 1: G F M N D G N H K K 2: H I C K H E H E I G 3: G C C L N F M K C E 4: A K G O I C C B O I 5: K O E B M O F C L N 6: D H K H I N B F A H 7: J N D J L K M A O O 8: J D I M O H N O H H
我们得到
diagnosis A B C D E F G H I J K L M N O 1: A 0 2 1 2 0 1 1 1 2 1 3 1 1 2 2 2: B 2 0 2 1 1 2 1 1 2 0 3 1 1 2 2 3: C 1 2 0 0 3 2 3 1 2 0 4 2 2 2 2 4: D 2 1 0 0 0 2 1 3 2 2 3 1 3 4 2 5: E 0 1 3 0 0 2 2 1 1 0 3 2 2 2 1 6: F 1 2 2 2 2 0 2 2 1 0 4 2 3 4 1 7: G 1 1 3 1 2 2 0 2 2 0 4 1 2 2 1 8: H 1 1 1 3 1 2 2 0 3 1 3 0 2 3 1 9: I 2 2 2 2 1 1 2 3 0 1 3 0 1 2 2 10: J 1 0 0 2 0 0 0 1 1 0 1 1 2 2 2 11: K 3 3 4 3 3 4 4 3 3 1 0 3 4 5 3 12: L 1 1 2 1 2 2 1 0 0 1 3 0 3 3 2 13: M 1 1 2 3 2 3 2 2 1 2 4 3 0 5 3 14: N 2 2 2 4 2 4 2 3 2 2 5 3 5 0 3 15: O 2 2 2 2 1 1 1 1 2 2 3 2 3 3 0
出于某种我还不明白的原因,需要在 set.seed(357)
之前调用 RNGversion("3.6.0")
才能重现 Roman 的随机数。
请注意,此测试用例包含每个患者的重复诊断,例如,第 1 行中的 K
。
这是另一个使用 table
的基本 R 选项:
pairs <- as.data.frame(do.call(rbind,
apply(dat, 1L, function(x) t(combn(na.omit(x), 2L)))))
tab <- table(pairs)
ut <- tab
ut[lower.tri(tab)] <- 0L
lt <- tab
lt[upper.tri(tab)] <- 0L
ans <- t(lt) + ut
ans + t(ans)
输出:
V1
V2 A B C D E F
A 0 2 2 2 3 2
B 2 0 2 2 1 1
C 2 2 0 2 1 1
D 2 2 2 0 1 1
E 3 1 1 1 0 2
F 2 1 1 1 2 0
数据:
dat <- read.table(text="V1 V2 V3 V4 V5 V6 V7
A B C D NA NA NA
A E F NA NA NA NA
D A C B 'F' E NA
A E NA NA NA NA NA", header=TRUE, colClasses="character")