我有一个包含3列的大型数据集,Order,Discharge,Date(数字)。每个订单的每日排放值有20年,可以超过100个。
> head(dat)
Order Discharge date
1 0.04712 6574
2 0.05108 6574
3 0.00000 6574
4 0.00000 6574
5 3.54100 6574
6 3.61500 6574
对于给定的订单x,我想将放电值替换为该日期的x + 1和x-1的放电平均值。我一直在以粗略的方式使用for循环和索引,但处理需要一个多小时。我知道必须有更好的方法。
x <- 4
for(i in min(dat[,3]):max(dat[,3]))
dat[,2][dat[,3] == i & dat[,1] == x ] <-
mean(c(dat[,2][dat[,3] == i & dat[,1] == x + 1],
dat[,2][dat[,3] == i & dat[,1] == x - 1]))
给予
> head(dat)
Order Discharge date
1 0.04712 6574
2 0.05108 6574
3 0.00000 6574
4 1.77050 6574
5 3.54100 6574
6 3.61500 6574
第4号订单的卸货,6574号的日期已被1.77050取代。它有效,但它的速度非常慢。
我应该指定我不需要对每个订单进行此计算,而只需要选择少数(总共117个中的8个)。根据答案,我有以下内容。
dat$NewDischarge <- by(dat$Discharge,dat$date,function(x)
colMeans(cbind(c(x[-1],NA), x,
c(NA, x[-length(x)])), na.rm=T))
我试图找出一种方法,只是计算选择订单的价值,并停留在for循环的车辙和日期和订单的索引上。
答案 0 :(得分:0)
我会按照以下方式去做:
Order
是一个因素。date
对子数据框进行排序。Discharge
- 均值可以“vectorally”生成:
colMeans(cbind(c(Discharge[-1], NA), Discharge, c(NA, Discharge[-length(Discharge)])))
by
来处理。我更希望by
。对于2.2点,想象一下(或尝试一下)一个简单的向量,看看cbind
操作的效果。它还迫使你考虑极限情况;如何计算第一个和最后一个排放值(没有先前或进行日期)。
答案 1 :(得分:0)
有几种方法可以解决您的特定困境,但遇到慢for
循环时要问的基本问题是,“如何使用矢量化来替换此循环?” (好吧,也许你应该首先问“我应该......?”。)在你的情况下,你是在循环日期,但没有必要明确地这样做,因为只需抓住{{1}的所有行将隐含地抓住所有日期。
您发布的数据集只有一个日期,但我可以生成一些假数据来说明:
dat$Order==x
以下是所有日期generate.data <- function(n.order, n.date){
dat <- expand.grid(Order=seq_len(n.order), date=seq_len(n.date))
dat$Discharge <- rlnorm(n.order * n.date)
dat[, c("Order", "Discharge", "date")]
}
dat <- generate.data(10, 5)
head(dat)
# Order Discharge date
# 1 1 2.1925563 1
# 2 2 0.4093022 1
# 3 3 2.5525497 1
# 4 4 1.9274013 1
# 5 5 1.1941986 1
# 6 6 1.2407451 1
tail(dat)
# Order Discharge date
# 45 5 1.4344575 5
# 46 6 0.5757580 5
# 47 7 0.4986190 5
# 48 8 1.2076292 5
# 49 9 0.3724899 5
# 50 10 0.8288401 5
的所有行:
dat$Order==4
您可以点击dat[dat$Order==4, ]
# Order Discharge date
# 4 4 1.9274013 1
# 14 4 3.5319072 2
# 24 4 0.2374532 3
# 34 4 0.4549798 4
# 44 4 0.7654059 5
列,然后您将拥有作业的左侧:
Discharge
现在你只需要右侧,它有两个组成部分:dat[dat$Order==4, ]$Discharge
# [1] 1.9274013 3.5319072 0.2374532 0.4549798 0.7654059
放电和x-1
放电。您可以像抓取x+1
放电一样抓住这些:
x
要获取新值,您需要并行平均值。 R没有dat[dat$Order==4-1, ]$Discharge
# [1] 2.5525497 1.9143963 0.2800546 8.3627810 7.8577635
dat[dat$Order==4+1, ]$Discharge
# [1] 1.1941986 4.6076114 0.3963693 0.4190957 1.4344575
功能,但您可以pmean
这些功能并使用cbind
:
rowMeans
所以,最后你有:
rowMeans(cbind(dat[dat$Order==4-1, ]$Discharge, dat[dat$Order==4+1, ]$Discharge))
# [1] 1.8733741 3.2610039 0.3382119 4.3909383 4.6461105
您甚至可以使用dat[dat$Order==4, ]$Discharge <- rowMeans(cbind(dat[dat$Order==4-1, ]$Discharge,
dat[dat$Order==4+1, ]$Discharge))
来完成所有%in%
值的工作。
请注意,这假设您的数据已订购。