我正在寻找一种快速有效的方法来计算下面描述的问题。任何帮助将不胜感激,在此先感谢!向量化“查找”功能的正确方法
我有几个非常大的csv文件,它们具有关于同一个对象的不同信息,但是在我的最终计算中,我需要不同表中的所有属性。我试图计算大量变电站的负载,首先我列出了一个独特的变电站清单;
Unique_Substations <- data.frame(Name = c("SubA", "SubB", "SubC", "SubD"))
在另一个列表中,我有关于这些变电站后面客户的信息;
Customer_Information <- data.frame(
Customer = 1001:1010,
SubSt_Nm = sample(unique(Unique_Substations$Name), 10, replace = TRUE),
HouseHoldType = sample(1:2, 10, replace = TRUE)
)
而在另一份名单我有信息,让我们说,对这些客户的屋顶太阳能电池板(不同年份);
Solar_Panels <- data.frame(
Customer = sample(1001:1010, 10, replace = TRUE),
SolarPanelYear1 = sample(10:20, 10, replace = TRUE),
SolarPanelYear2 = sample(15:20, 10, replace = TRUE)
)
现在我想看看每个变电站每年的负载是多少。我有一个家庭负载和一个太阳能电池板负载正常化的每种类型的家庭或solarpanel;
SolarLoad <- data.frame(Load = c(0, -10, -10, 5))
HouseHoldLoad <- data.frame(Type1 = c(1, 3, 5, 2), Type2 = c(3, 5, 6, 1))
所以现在我必须匹配这些列表;
ML_SubSt_Cust <- sapply(Unique_Substations$Name,
function(x) which(Customer_Information$SubSt_Nm %in% x == TRUE))
ML_Cust_SolarP <- sapply(Customer_Information$Customer,
function(x) which(Solar_Panels$Customer %in% x == TRUE))
(这里我用的which(xxx %in% x == TRUE)
方法,因为我需要多比赛和match()
只返回一个匹配
现在我们来到我的大问题(但可能不是我唯一的,最后用这种方法的问题)我想计算每个变电站每年的最大负载,为此我首先编写了一个for循环,通过Unique_Substations列表循环,这当然是非常低效的。之后我尝试使用outer()
来加速它,但是我认为我没有正确地将我的功能向量化,我的最大功能如下所示(我只写了太阳能电池板部分以保留我简单);
GetMax <- function(i, Yr) {
max(sum(Solar_Panels[unlist(ML_Cust_SolarP[ML_SubSt_Cust[[i]]], use.names= FALSE),Yr])*SolarLoad)
}
我确定这根本没有效率,但我不知道如何以任何其他方式做到这一点。
为了得到我的最终结果,我使用了一个外部函数;
Results <- outer(1:nrow(Unique_Substations), 1:2, Vectorize(GetMax))
在我的例子所有这些数据的帧是非常非常大(每个左右40000行),所以我真正需要的参与功能的一些很好的优化。我试图想方法来矢量化函数,但我无法解决这个问题。任何帮助,将不胜感激。
编辑:
现在,我完全理解接受awnser我还有一个问题。我的实际Customer_Information
是188K行长,我的实际HouseHoldLoad
是53K行长。不用说这不是merge()
非常好。是否有另一种解决方案,不需要merge()
或循环太慢?
首先,你不需要'data.frames',因为只有一个数据类型每个对象。向量和矩阵就足够了。接下来,不是'which(foo%in%bar == TRUE)',而只是'which(bar == foo)'(其中'foo'是一个标量,'bar'是你的向量或矩阵)。 – 2014-08-28 11:20:47
@CarlWitthoft'which(foo%in%bar == TRUE)'与'which(foo%in%bar)'相同,而不是'which(bar == foo)'。拿'bar = c(0,1)'和'foo = c(1,0)',差别很明显。我同意你可以在'foo'只包含一个元素时使用,但它们不一样。 – 2014-08-28 11:52:57
@JorisMeys谢谢 - 好点 – 2014-08-28 12:37:39