我有一个很大的数据框,其中每一行代表一个事件的单个实例。出于说明目的,请考虑一个包含以下五列的数据框:
请参见下面的可复制示例。
library(dplyr)
library(lubridate)
set.seed(5567)
df <- data.frame(time = sample(seq(as.POSIXct('2019/01/10'),
as.POSIXct('2019/01/20'),
by="15 mins"), 100))
df <- mutate(df,
two.Before = df$time - hours(2),
two.After = df$time + hours(2),
loc = sample(c("New York", "Boston", "Atlanta", "Chicago"), 100,
replace=TRUE) %>% as.factor,
type = sample(c("Bus", "Car"), 100,
replace=TRUE) %>% as.factor)
head(df)
对于每个实例,我需要创建两个新列:
如果有人可以帮助您,将不胜感激。我的约会全都是posixCt,类别都是因素。非常感谢!
答案 0 :(得分:0)
我这样做的方法是循环。运行时很高,但是可以正常运行。
首先是col1
,该数字计算的是同一城市在+ -2小时内发生的次数。
注意:循环的最后一行执行-1
,这是为了消除对第一次观察的重复计数。
第二个是col2
,其功能与上述相同,但还包括type =“ Bus”。
注意:循环的最后一行这样做-1
,以消除对第一次观察的重复计数(与第一个循环有些不同,因为我们需要确保首先观察到的观察次数不止一次,因为不是全部类型是“公共汽车”)。
df$col1<-0
for (i in 1:nrow(df)){
for (j in 1:nrow(df)){
if (hour(df[i,]$time)==hour(df[j,]$time) & df[i,]$loc==df[j,]$loc)
{df[i,]$col1<-df[i,]$col1+1}
else if ((hour(df[i,]$time)-hour(df[j,]$time))<2 & (hour(df[i,]$time)-hour(df[j,]$time))>(-2) & df[i,]$loc==df[j,]$loc)
{df[i,]$col1<-df[i,]$col1+1}
}
df[i,]$col1<-df[i,]$col1-1
}
df$col2<-0
for (i in 1:nrow(df)){
for (j in 1:nrow(df)){
if (hour(df[i,]$time)==hour(df[j,]$time) & df[i,]$loc==df[j,]$loc & df[j,]$type=="Bus")
{df[i,]$col2<-df[i,]$col2+1}
else if ((hour(df[i,]$time)-hour(df[j,]$time))<2 & (hour(df[i,]$time)-hour(df[j,]$time))>(-2) &
df[i,]$loc==df[j,]$loc & df[j,]$type=="Bus")
{df[i,]$col2<-df[i,]$col2+1}
}
if (df[i,]$col2>0){df[i,]$col2<-df[i,]$col2-1}
}
您可以输入head(df)
来查看结果,也可以只查看整个数据集。
如果您对代码的任何部分有任何疑问,请告诉我。
答案 1 :(得分:0)
在r中使用循环通常是次优的想法,因为任何中等数据集都会陷入困境。如果您对此感兴趣,请在其他堆栈溢出答案中指定原因。 r中的最佳实践是,如果您正在考虑使用for循环遍历数据帧中的所有记录,请改用函数apply family。
我在下面编写了一些快速代码,这些代码可以相当快地完成技巧,并以您提供的代码为基础。
df$row <- rownames(df)
#Column 1: count occurrences +/- 2hrs within same city
df$col1 <- mapply(function(time, city, row) sum(df[df$row != row,"two.Before"] <= time & df[df$row != row,"two.After"] >= time & df[df$row != row,"loc"] == city),
df$time, df$loc, df$row)
#Column2: count occurrences +/- 2hrs within same city and on a bus
df$col2 <- mapply(function(time, city, bus, row) sum(df[df$row != row,"two.Before"] <= time & df[df$row != row,"two.After"] >= time & df[df$row != row,"loc"] == city & df[df$row != row,"type"] == "Bus"),
df$time, df$loc, df$type, df$row)
#Remove row index
df <- subset(df, select = -c(row))
如果您有任何疑问,请告诉我。它似乎按我测试的几个数据点的预期工作。假设您不想在两次计数中都计算该行,否则所有col1计数均为1。
下面仅显示事件发生前两个小时的代码(再次基于提供的代码)。
df$row <- as.numeric(rownames(df))
#Column 1: count occurrences +/- 2hrs within same city
df$col1 <- mapply(function(time, city, row) sum(df[df$row != row,"time"] <= time & df[df$row != row,"two.After"] >= time & df[df$row != row,"loc"] == city),
df$time, df$loc, df$row)
#Column2: count occurrences +/- 2hrs within same city and on a bus
df$col2 <- mapply(function(time, city, bus, row) sum(df[df$row != row,"time"] <= time & df[df$row != row,"two.After"] >= time & df[df$row != row,"loc"] == city & df[df$row != row,"type"] == "Bus"),
df$time, df$loc, df$type, df$row)