以下是我数据框的示例
charact_fraction pure_charact sample replicate identity
0.08348135 clean An006 1 70
0.078947368 clean An006 1 70
0.090277778 clean An006 1 70
0.044399596 clean An006 2 70
0 clean An006 2 70
0.049348869 clean An006 2 70
0.218818381 mixed An011 1 70
0.112068966 mixed An011 1 70
1 pure An011 1 70
0 clean An011 2 70
0.214285714 mixed An011 2 70
0.2180937 mixed An011 2 70
我想要对charact_fraction
进行分区并计算按多个因素分组的bin频率。生成的数据框应该看起来像这样
bin_frequency bin sample replicate identity
… 0-0.1 An006 1 70
… … … … …
… 0.9-1.0 An006 1 70
… 0-0.1 An011 1 70
… … … … …
… 0.9-1.0 An011 1 70
… … … … …
我有返回bin频率的功能。
get_freqs <- function(dat_vector, breaks) {
hist(dat_vector, breaks=breaks, include.lowest=TRUE, plot=FALSE)$counts
}
我可以生成垃圾箱。
breaks=seq(0,1,by=0.1)
bins = paste(breaks, breaks[-1], sep="-")
bins = bins[-length(ranges)]
我相信这是我到目前为止最接近的镜头,但显然远远不是预期的输出:
with(df, tapply(charact_part, list(sample, replicate, identity), get_freqs, breaks=breaks))
我有非常丑陋的Python代码可以做到这一点,但我希望在R中有更清洁和更实用的功能。先谢谢你。
答案 0 :(得分:1)
cut
可能是要走的路:
x <- gsub("\\[|\\]|\\(", "", cut(df$charact_fraction, seq(0,1, .1), include.lowest=T))
df$range <- gsub(",", "-", x)
df
# charact_fraction pure_charact sample replicate identity range
# 1 0.08348135 clean An006 1 70 0-0.1
# 2 0.07894737 clean An006 1 70 0-0.1
# 3 0.09027778 clean An006 1 70 0-0.1
# 4 0.04439960 clean An006 2 70 0-0.1
# 5 0.00000000 clean An006 2 70 0-0.1
# 6 0.04934887 clean An006 2 70 0-0.1
# 7 0.21881838 mixed An011 1 70 0.2-0.3
# 8 0.11206897 mixed An011 1 70 0.1-0.2
# 9 1.00000000 pure An011 1 70 0.9-1
# 10 0.00000000 clean An011 2 70 0-0.1
# 11 0.21428571 mixed An011 2 70 0.2-0.3
# 12 0.21809370 mixed An011 2 70 0.2-0.3
如果您还想要计数,可以添加:
lst <- lapply(split(df, df$sample), function(x) {
within(x, count <- table(range)[match(range, names(table(range)))])
})
`rownames<-`(do.call(rbind, lst), NULL)
# charact_fraction pure_charact sample replicate identity range count
# 1 0.08348135 clean An006 1 70 0-0.1 6
# 2 0.07894737 clean An006 1 70 0-0.1 6
# 3 0.09027778 clean An006 1 70 0-0.1 6
# 4 0.04439960 clean An006 2 70 0-0.1 6
# 5 0.00000000 clean An006 2 70 0-0.1 6
# 6 0.04934887 clean An006 2 70 0-0.1 6
# 7 0.21881838 mixed An011 1 70 0.2-0.3 3
# 8 0.11206897 mixed An011 1 70 0.1-0.2 1
# 9 1.00000000 pure An011 1 70 0.9-1 1
# 10 0.00000000 clean An011 2 70 0-0.1 1
# 11 0.21428571 mixed An011 2 70 0.2-0.3 3
# 12 0.21809370 mixed An011 2 70 0.2-0.3 3
答案 1 :(得分:1)
来自'plyr'的cut()
和ddply()
的组合应该为您提供一个数据框,其中包含您感兴趣因子的各个子集的频率。如下所示:
library(plyr)
df$bin <- cut(df$charact_fraction, seq(0, 1, 0.1), include.lowest=TRUE)
df$obs <- 1 # Makes counting easy in next step
xtabs <- ddply(df, .(bin, sample, replicate, identity), summarise,
frequency = sum(obs))
这里使用ddply的一个潜在缺点是结果数据帧不包含零观测值的子集。如果这是一个问题,你可以创建一个完整的矩阵,合并观察到的频率,然后用这样的0替换NA:
xtabs.grid <- with(df, expand.grid(bin = unique(bins), sample = unique(sample),
replicate = unique(replicate), identity = unique(identity)))
xtabs.full <- merge(xtabs.grid, xtabs, all.x = TRUE)
xtabs.full[is.na(xtabs.full)] <- 0
请注意,为了使合并顺利进行,提供给expand.grid()
的变量名称需要与前一步骤中ddply()
生成的变量名称相匹配。
附录:这是一个使用'dplyr'功能和管道来一次完成所有这些的版本:
df2 <- df %>%
mutate(bin = cut(charact_fraction, seq(0, 1, 0.1), include.lowest=TRUE)) %>%
count(bin, sample, replicate, identity) %>%
left_join(with(df, expand.grid(bin=levels(cut(charact_fraction, seq(0, 1, 0.1), include.lowest=TRUE)), sample=unique(sample), replicate=unique(replicate), identity=unique(identity))), .) %>%
mutate(n = ifelse(is.na(n)==FALSE, n, 0))
答案 2 :(得分:0)
只需使用table
:
with( dfrm, table( cut( charact_function, breaks=10, include.lowest=TRUE),
sample, replicate, identity) )
您也可以使用breaks=breaks
,但我只想展示该参数的不同用法...稍微更紧凑。
这是一种4路分类,虽然你可能想要三种双向分类,在这种情况下它是:
cat_char_func <- cut( charact_function, breaks=10, include.lowest=TRUE)
sapply( dfrm[ , c('sample', 'replicate', 'identity')],
function(cat) { table( cat_char_func, cat) }
)