R - 按组计算不匹配
R - Compute Mismatch By Group
我想知道如何按组计算不匹配 个案例。
让我们想象这是我的数据:
sek = rbind(c(1, 'a', 'a', 'a'),
c(1, 'a', 'a', 'a'),
c(2, 'b', 'b', 'b'),
c(2, 'c', 'b', 'b'))
colnames(sek) <- c('Group', paste('t', 1:3, sep = ''))
数据是这样的
Group t1 t2 t3
[1,] "1" "a" "a" "a"
[2,] "1" "a" "a" "a"
[3,] "2" "b" "b" "b"
[4,] "2" "c" "b" "b"
为了得到类似
的东西
Group 1 : 0
Group 2 : 1
最好使用 stringdist
库来计算它。
类似于
seqdistgroupStr = function(x) stringdistmatrix(x, method = 'hamming')
sek %>%
as.data.frame() %>%
group_by(Group) %>%
seqdistgroupStr()
但它不起作用。
有什么想法吗?
快速更新:
你会如何解决权重问题?例如,当在两个字符之间设置 mistmatch 时,我如何传递一个参数 - 一个值 (1,2,3, ...)。就像 b 和 c 之间的 mismatch 成本 2 而 mismatch 在 a 和 c 之间花费 1 等等。
下面的代码将为您提供按组划分的不匹配数,其中不匹配被定义为比组的每个级别的每列 t1、t2 等中的唯一值的数量少一个。我认为只有当您需要的不仅仅是不匹配的二进制度量时,您才需要引入字符串距离度量,但是二进制度量足以满足您给出的示例。另外,如果你想要的只是每组中不同行的数量,那么@Alex 的解决方案更简洁。
library(dplyr)
library(reshape2)
sek %>% as.data.frame %>%
melt(id.var="Group") %>%
group_by(Group, variable) %>%
summarise(mismatch = length(unique(value)) - 1) %>%
group_by(Group) %>%
summarise(mismatch = sum(mismatch))
Group mismatch
1 1 0
2 2 1
这里有一个较短的 dplyr
方法来计算单个不匹配项。不需要reshaping,但是需要其他数据体操:
sek %>% as.data.frame %>%
group_by(Group) %>%
summarise_each(funs(length(unique(.)) - 1)) %>%
mutate(mismatch = rowSums(.[-1])) %>%
select(-matches("^t[1-3]$"))
m <- matrix(apply(sek[,-1], 1, paste, collapse=''))
newdf <- as.data.frame(cbind(sek[,1], m))
names(newdf) <- c('Group', 'value')
newdf %>% group_by(Group) %>% summarize(count = length(unique(value))-1)
# Group count
#1 1 0
#2 2 1
另一个想法:
library(dplyr)
library(tidyr)
data.frame(sek) %>%
gather(key, value, -Group) %>%
group_by(Group) %>%
summarise(dist = n_distinct(value)-1)
给出:
#Source: local data frame [2 x 2]
#
# Group dist
#1 1 0
#2 2 1
这是另一个 dplyr
解决方案,不需要将数据转换为 long/wide 形式:
library(dplyr)
sek = rbind(c(1, 'a', 'a', 'a'),
c(1, 'a', 'a', 'a'),
c(2, 'b', 'b', 'b'),
c(2, 'c', 'b', 'b')) %>%
data.frame
colnames(sek) <- c('Group', paste('t', 1:3, sep = ''))
sek %>%
group_by(Group) %>%
distinct(t1, t2, t3) %>%
summarise(number_of_mismatches = n() - 1)
基础包:
aggregate(cbind(dist = Groups) ~ Groups,
data = unique(sek),
FUN = function(x){NROW(x)-1})
与sqldf
:
library(sqldf)
df <- rbind(c(1, "a", "a", "a"),
c(1, "a", "a", "a"),
c(2, "b", "b", "b"),
c(2, "c", "b", "b"))
df <- as.data.frame(df)
colnames(df)[1] <- "Groups"
sqldf("SELECT Groups, COUNT(Groups)-1 AS Dist
FROM (SELECT DISTINCT * FROM df)
GROUP BY Groups")
输出:
Groups Dist
1 1 0
2 2 1
我想知道如何按组计算不匹配 个案例。
让我们想象这是我的数据:
sek = rbind(c(1, 'a', 'a', 'a'),
c(1, 'a', 'a', 'a'),
c(2, 'b', 'b', 'b'),
c(2, 'c', 'b', 'b'))
colnames(sek) <- c('Group', paste('t', 1:3, sep = ''))
数据是这样的
Group t1 t2 t3
[1,] "1" "a" "a" "a"
[2,] "1" "a" "a" "a"
[3,] "2" "b" "b" "b"
[4,] "2" "c" "b" "b"
为了得到类似
的东西Group 1 : 0
Group 2 : 1
最好使用 stringdist
库来计算它。
类似于
seqdistgroupStr = function(x) stringdistmatrix(x, method = 'hamming')
sek %>%
as.data.frame() %>%
group_by(Group) %>%
seqdistgroupStr()
但它不起作用。
有什么想法吗?
快速更新: 你会如何解决权重问题?例如,当在两个字符之间设置 mistmatch 时,我如何传递一个参数 - 一个值 (1,2,3, ...)。就像 b 和 c 之间的 mismatch 成本 2 而 mismatch 在 a 和 c 之间花费 1 等等。
下面的代码将为您提供按组划分的不匹配数,其中不匹配被定义为比组的每个级别的每列 t1、t2 等中的唯一值的数量少一个。我认为只有当您需要的不仅仅是不匹配的二进制度量时,您才需要引入字符串距离度量,但是二进制度量足以满足您给出的示例。另外,如果你想要的只是每组中不同行的数量,那么@Alex 的解决方案更简洁。
library(dplyr)
library(reshape2)
sek %>% as.data.frame %>%
melt(id.var="Group") %>%
group_by(Group, variable) %>%
summarise(mismatch = length(unique(value)) - 1) %>%
group_by(Group) %>%
summarise(mismatch = sum(mismatch))
Group mismatch
1 1 0
2 2 1
这里有一个较短的 dplyr
方法来计算单个不匹配项。不需要reshaping,但是需要其他数据体操:
sek %>% as.data.frame %>%
group_by(Group) %>%
summarise_each(funs(length(unique(.)) - 1)) %>%
mutate(mismatch = rowSums(.[-1])) %>%
select(-matches("^t[1-3]$"))
m <- matrix(apply(sek[,-1], 1, paste, collapse=''))
newdf <- as.data.frame(cbind(sek[,1], m))
names(newdf) <- c('Group', 'value')
newdf %>% group_by(Group) %>% summarize(count = length(unique(value))-1)
# Group count
#1 1 0
#2 2 1
另一个想法:
library(dplyr)
library(tidyr)
data.frame(sek) %>%
gather(key, value, -Group) %>%
group_by(Group) %>%
summarise(dist = n_distinct(value)-1)
给出:
#Source: local data frame [2 x 2]
#
# Group dist
#1 1 0
#2 2 1
这是另一个 dplyr
解决方案,不需要将数据转换为 long/wide 形式:
library(dplyr)
sek = rbind(c(1, 'a', 'a', 'a'),
c(1, 'a', 'a', 'a'),
c(2, 'b', 'b', 'b'),
c(2, 'c', 'b', 'b')) %>%
data.frame
colnames(sek) <- c('Group', paste('t', 1:3, sep = ''))
sek %>%
group_by(Group) %>%
distinct(t1, t2, t3) %>%
summarise(number_of_mismatches = n() - 1)
基础包:
aggregate(cbind(dist = Groups) ~ Groups,
data = unique(sek),
FUN = function(x){NROW(x)-1})
与sqldf
:
library(sqldf)
df <- rbind(c(1, "a", "a", "a"),
c(1, "a", "a", "a"),
c(2, "b", "b", "b"),
c(2, "c", "b", "b"))
df <- as.data.frame(df)
colnames(df)[1] <- "Groups"
sqldf("SELECT Groups, COUNT(Groups)-1 AS Dist
FROM (SELECT DISTINCT * FROM df)
GROUP BY Groups")
输出:
Groups Dist
1 1 0
2 2 1