在对重复标识符进行操作时避免循环
Avoiding looping when operations on repeated identifier
我经常很难在 R 中进行基本操作,因为我必须控制唯一标识符。
我大部分时间都在处理 "long format" 数据。
dt <- data.frame(id = c(rep("A1", 3), rep("B1", 3)),
activity = c(15,17,12,3,4,15),
begin = c( 0, 0, 1, 0, 1, 2 ) )
例如,通过标识符计算时间或观察
dt$time <- 1
for(i in 2:nrow(dt)){
if(dt[i,'id'] == dt[i-1, 'id'])
{
dt[i,'time'] <- dt[i-1,'time'] + 1
}
}
或仔细检查重复数据
dt$zerocheck = 0
for(i in 2:nrow(dt)){
if( dt[i,'id'] == dt[i-1, 'id'] &
dt[i,'begin'] == dt[i-1, 'begin'] )
{
dt$zerocheck[i] <- 1
}
}
我想答案应该是按 id 聚合之类的东西,但我不完全确定。
merge(dt, aggregate(time ~ id, dt, "max"), by=c("id"), all.X=T)
有什么避免循环的建议吗?
这些操作可以用data.table
来简化:
require(data.table)
setDT(dt)[, `:=`(time = seq_len(.N), zerocheck = begin == shift(begin)), by = id]
要添加到其他示例,您还可以使用 dplyr
library(dplyr)
dt %>% group_by(id) %>%
mutate(time = row_number()) %>% # creates the control for identifier
mutate(zerocheck= ifelse(begin==lag(begin), 1, 0)) # checks for repeated data
或者等效地,您可以只使用如下所示的单个 mutate 函数:
dt %>%
group_by(id) %>%
mutate(time = row_number(),
zerocheck=begin==lag(begin))
第一个查询有输出:
Source: local data frame [6 x 5]
Groups: id
id activity begin time zerocheck
1 A1 15 0 1 NA
2 A1 17 0 2 1
3 A1 12 1 3 0
4 B1 3 0 1 NA
5 B1 4 1 2 0
6 B1 15 2 3 0
对于 zerocheck
的情况,我只是使用滞后来检查之前的值是否与当前值相同。这模仿了您问题中的代码。当然如果你想检查别的东西,你可以很容易地改变谓词。
我经常很难在 R 中进行基本操作,因为我必须控制唯一标识符。
我大部分时间都在处理 "long format" 数据。
dt <- data.frame(id = c(rep("A1", 3), rep("B1", 3)),
activity = c(15,17,12,3,4,15),
begin = c( 0, 0, 1, 0, 1, 2 ) )
例如,通过标识符计算时间或观察
dt$time <- 1
for(i in 2:nrow(dt)){
if(dt[i,'id'] == dt[i-1, 'id'])
{
dt[i,'time'] <- dt[i-1,'time'] + 1
}
}
或仔细检查重复数据
dt$zerocheck = 0
for(i in 2:nrow(dt)){
if( dt[i,'id'] == dt[i-1, 'id'] &
dt[i,'begin'] == dt[i-1, 'begin'] )
{
dt$zerocheck[i] <- 1
}
}
我想答案应该是按 id 聚合之类的东西,但我不完全确定。
merge(dt, aggregate(time ~ id, dt, "max"), by=c("id"), all.X=T)
有什么避免循环的建议吗?
这些操作可以用data.table
来简化:
require(data.table)
setDT(dt)[, `:=`(time = seq_len(.N), zerocheck = begin == shift(begin)), by = id]
要添加到其他示例,您还可以使用 dplyr
library(dplyr)
dt %>% group_by(id) %>%
mutate(time = row_number()) %>% # creates the control for identifier
mutate(zerocheck= ifelse(begin==lag(begin), 1, 0)) # checks for repeated data
或者等效地,您可以只使用如下所示的单个 mutate 函数:
dt %>%
group_by(id) %>%
mutate(time = row_number(),
zerocheck=begin==lag(begin))
第一个查询有输出:
Source: local data frame [6 x 5]
Groups: id
id activity begin time zerocheck
1 A1 15 0 1 NA
2 A1 17 0 2 1
3 A1 12 1 3 0
4 B1 3 0 1 NA
5 B1 4 1 2 0
6 B1 15 2 3 0
对于 zerocheck
的情况,我只是使用滞后来检查之前的值是否与当前值相同。这模仿了您问题中的代码。当然如果你想检查别的东西,你可以很容易地改变谓词。