我想使用行为数据来计算捕获的物品数量。这是我的示例数据:
df <- data.frame(id = as.factor(c(51,51,51,51,51,51,51,52,52,52,52,52,52)),
type = c("(K)","(K)","(K)","(K)","","","","(K)","(K)","","(K)","","(K)"))
我想根据它们是否连续来计算我的每个“K”。如果是连续的,则字符串应计为1。如果它们之间存在差距,它们都应该算作一个......所以最终的结果将是2.
希望有意义......对于上面的例子,我希望我的最终输出数据看起来像这样
id type tally
1 51 (K) 1
2 52 (K) 3
我认为聚合可能会这样做,但它会计算一列中的总数,因此对于51 tally = 4而不是1
任何帮助将不胜感激
由于 格雷斯
答案 0 :(得分:4)
在基础R中,您可以使用rle
执行此操作。首先按df
分割id
,然后为每个子组计算"(K)"
的序列次数。
sapply(split(df, df$id), function(a)
length(with(rle(as.character(a$type)), lengths[values == "(K)"])))
#51 52
# 1 3
答案 1 :(得分:3)
我们可以使用rleid
中的data.table
进行尝试。转换&#39; data.frame&#39;到&#39; data.table&#39; (setDT(df)
),按&#39; id&#39;分组,找到&#39;类型&#39;的运行长度ID,按&#39; id&#39;分组,&# 39;输入&#39;,获取&#39; val&#39;的length
元素的unique
这不是空白
library(data.table)
setDT(df)[, val := rleid(type), id][type!="", .(tally = uniqueN(val)), .(id, type)]
# id type tally
#1: 51 (K) 1
#2: 52 (K) 3
或者我们可以使用tidyverse
library(tidyverse)
df %>%
mutate(val = cumsum(type != lag(type, default = type[1]))) %>%
group_by(id) %>%
filter(type!="") %>%
summarise(type = first(type), tally= n_distinct(val))
# A tibble: 2 × 3
# id type tally
# <fctr> <fctr> <int>
#1 51 (K) 1
#2 52 (K) 3
答案 2 :(得分:3)
基础R中的rle
命令很有用。
temp<- tapply(df$type, df$id, function(x) rle(x == "(K)"))
df.new<- data.frame(id = names(temp),
tally = unlist(lapply(temp, function(x) sum(x$values))))