将值替换为基于两个 类 的平均值
Replace value with the mean based on two classes
我有一个 dataset
,其中包含 2 个日历变量(Week
和 Hour
)和 1 个 Amount
变量:
Week Hour Amount
35 1 367
35 2 912
36 1 813
36 2 482
37 1 112
37 2 155
35 1 182
35 2 912
36 1 551
36 2 928
37 1 125
37 2 676
我希望用相同 Week/Hour 对的每次观察的平均值替换 Amount
的每个值。例如,这里有 2 个 obs。对于 (Week=35
, Hour=1
),Amount
值为 367
和 182
。因此,对于此示例,具有 (Week=35
、Hour=1
) 的 2 行应将 Amount
替换为 mean(c(367,182)
。最终输出应该是:
Week Hour Amount
35 1 274.5
35 2 912.0
36 1 682.0
36 2 705.0
37 1 118.5
37 2 415.5
35 1 274.5
35 2 912.0
36 1 682.0
36 2 705.0
37 1 118.5
37 2 415.5
我有以下代码可以解决这个问题。但是,对于数千行的完整数据集,速度非常慢。有什么方法可以用这种配对方式自动重塑吗?
dataset = data.frame(Week=c(35,35,36,36,37,37,35,35,36,36,37,37),
Hour = c(1,2,1,2,1,2,1,2,1,2,1,2),
Amount = c(367,912,813,482,112,155,182,912,551,928,125,676))
means <- reshape2::dcast(dataset, Week~Hour, value.var="Value", mean)
for (i in 1:nrow(dataset)) {
print(i)
dataset$Amount[i] <- means[means$Week==dataset$Week[i],which(colnames(means)==dataset$Hour[i])]
}
可能的解决方案dplyr
:
dataset %>%
group_by(Week, Hour) %>%
summarise(mean_amount = mean(Amount))
您按周和小时分组,并根据此条件计算平均值。
编辑
为了保持原始结构(行数)将代码更改为
dataset %>%
group_by(Week, Hour) %>%
mutate(Amount = mean(Amount))
如果这个想法只是通过 Week
和 Hour
获得平均值 Amount
,这将可行:
aggregate(Amount ~ ., dataset, mean)
Week Hour Amount
1 35 1 274.5
2 36 1 682.0
3 37 1 118.5
4 35 2 912.0
5 36 2 705.0
6 37 2 415.5
编辑:
但是,如果想法是将平均值放回 dataset
,那么这应该可行:
x <- aggregate(Amount ~ ., dataset, mean)
dataset$Amount <- x$Amount[match(apply(dataset[,1:2], 1, paste0, collapse = " "),
apply(x[,1:2], 1, paste0, collapse = " "))]
dataset
Week Hour Amount
1 35 1 274.5
2 35 2 912.0
3 36 1 682.0
4 36 2 705.0
5 37 1 118.5
6 37 2 415.5
7 35 1 274.5
8 35 2 912.0
9 36 1 682.0
10 36 2 705.0
11 37 1 118.5
12 37 2 415.5
解释:
这 paste
将平均值数据帧 x
中前两列的行组合成字符串 dataset
使用函数 apply
它使用 match
在这些字符串上将平均值分配给 dataset
中的相应行
编辑 2:
或者,您可以分别使用 interaction
和 %in%
进行此转换:
dataset$Amount <- x$Amount[match(interaction(dataset[,1:2]), interaction(x[,1:2]))]
# or:
dataset$Amount <- x$Amount[interaction(x[,1:2]) %in% interaction(dataset[,1:2])]
基础 R 解决方案:
dataset$Amount <- with(dataset, ave(dataset$Amount, dataset$Week, dataset$Hour, FUN = mean))
数据:
dataset = data.frame(Week=c(35,35,36,36,37,37,35,35,36,36,37,37),
Hour = c(1,2,1,2,1,2,1,2,1,2,1,2),
Amount = c(367,912,813,482,112,155,182,912,551,928,125,676))
我有一个 dataset
,其中包含 2 个日历变量(Week
和 Hour
)和 1 个 Amount
变量:
Week Hour Amount
35 1 367
35 2 912
36 1 813
36 2 482
37 1 112
37 2 155
35 1 182
35 2 912
36 1 551
36 2 928
37 1 125
37 2 676
我希望用相同 Week/Hour 对的每次观察的平均值替换 Amount
的每个值。例如,这里有 2 个 obs。对于 (Week=35
, Hour=1
),Amount
值为 367
和 182
。因此,对于此示例,具有 (Week=35
、Hour=1
) 的 2 行应将 Amount
替换为 mean(c(367,182)
。最终输出应该是:
Week Hour Amount
35 1 274.5
35 2 912.0
36 1 682.0
36 2 705.0
37 1 118.5
37 2 415.5
35 1 274.5
35 2 912.0
36 1 682.0
36 2 705.0
37 1 118.5
37 2 415.5
我有以下代码可以解决这个问题。但是,对于数千行的完整数据集,速度非常慢。有什么方法可以用这种配对方式自动重塑吗?
dataset = data.frame(Week=c(35,35,36,36,37,37,35,35,36,36,37,37),
Hour = c(1,2,1,2,1,2,1,2,1,2,1,2),
Amount = c(367,912,813,482,112,155,182,912,551,928,125,676))
means <- reshape2::dcast(dataset, Week~Hour, value.var="Value", mean)
for (i in 1:nrow(dataset)) {
print(i)
dataset$Amount[i] <- means[means$Week==dataset$Week[i],which(colnames(means)==dataset$Hour[i])]
}
可能的解决方案dplyr
:
dataset %>%
group_by(Week, Hour) %>%
summarise(mean_amount = mean(Amount))
您按周和小时分组,并根据此条件计算平均值。
编辑
为了保持原始结构(行数)将代码更改为
dataset %>%
group_by(Week, Hour) %>%
mutate(Amount = mean(Amount))
如果这个想法只是通过 Week
和 Hour
获得平均值 Amount
,这将可行:
aggregate(Amount ~ ., dataset, mean)
Week Hour Amount
1 35 1 274.5
2 36 1 682.0
3 37 1 118.5
4 35 2 912.0
5 36 2 705.0
6 37 2 415.5
编辑:
但是,如果想法是将平均值放回 dataset
,那么这应该可行:
x <- aggregate(Amount ~ ., dataset, mean)
dataset$Amount <- x$Amount[match(apply(dataset[,1:2], 1, paste0, collapse = " "),
apply(x[,1:2], 1, paste0, collapse = " "))]
dataset
Week Hour Amount
1 35 1 274.5
2 35 2 912.0
3 36 1 682.0
4 36 2 705.0
5 37 1 118.5
6 37 2 415.5
7 35 1 274.5
8 35 2 912.0
9 36 1 682.0
10 36 2 705.0
11 37 1 118.5
12 37 2 415.5
解释:
这 paste
将平均值数据帧 x
中前两列的行组合成字符串 dataset
使用函数 apply
它使用 match
在这些字符串上将平均值分配给 dataset
编辑 2:
或者,您可以分别使用 interaction
和 %in%
进行此转换:
dataset$Amount <- x$Amount[match(interaction(dataset[,1:2]), interaction(x[,1:2]))]
# or:
dataset$Amount <- x$Amount[interaction(x[,1:2]) %in% interaction(dataset[,1:2])]
基础 R 解决方案:
dataset$Amount <- with(dataset, ave(dataset$Amount, dataset$Week, dataset$Hour, FUN = mean))
数据:
dataset = data.frame(Week=c(35,35,36,36,37,37,35,35,36,36,37,37),
Hour = c(1,2,1,2,1,2,1,2,1,2,1,2),
Amount = c(367,912,813,482,112,155,182,912,551,928,125,676))