首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >“查找”函数矢量化的正确方法

“查找”函数矢量化的正确方法
EN

Stack Overflow用户
提问于 2014-08-28 09:20:28
回答 1查看 226关注 0票数 0

我正在寻找一种快速高效的方法来计算下面描述的问题。任何帮助都将不胜感激,谢谢提前!

我有两个非常大的csv文件,它们对同一个对象有不同的信息,但在最后的计算中,我需要不同表中的所有属性。我正在努力计算大量变电站的负荷,首先我有一个独特的变电站清单;

代码语言:javascript
运行
复制
Unique_Substations <- data.frame(Name = c("SubA", "SubB", "SubC", "SubD"))

在另一个列表中,我有关于这些变电站背后的客户的信息;

代码语言:javascript
运行
复制
Customer_Information <- data.frame(
  Customer = 1001:1010, 
  SubSt_Nm = sample(unique(Unique_Substations$Name), 10, replace = TRUE), 
  HouseHoldType = sample(1:2, 10, replace = TRUE)
)

在另一个列表中,我有关于这些客户屋顶上的太阳能电池板的信息(不同年份);

代码语言:javascript
运行
复制
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)
)

现在我想看看每年每个变电站的负荷是多少。我有一个家庭负荷和太阳能电池板负荷正常化的每户或太阳能电池板;

代码语言:javascript
运行
复制
SolarLoad <- data.frame(Load = c(0, -10, -10, 5))
HouseHoldLoad <- data.frame(Type1 = c(1, 3, 5, 2), Type2 = c(3, 5, 6, 1))

因此,现在我必须匹配这些清单;

代码语言:javascript
运行
复制
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()只返回一个匹配

现在我们来问我的大问题(但这可能不是我唯一的问题)。我想计算每个变电站每年的最大负荷。为此,我首先编写了一个遍历Unique_Substations列表的for循环,这当然是非常低效率的。之后,我尝试使用outer()加快速度,但我认为我没有正确地将函数向量化。我的最大功能如下(我只为太阳能电池板部分写出来,以保持它的简单);

代码语言:javascript
运行
复制
GetMax <- function(i, Yr) {
  max(sum(Solar_Panels[unlist(ML_Cust_SolarP[ML_SubSt_Cust[[i]]], use.names= FALSE),Yr])*SolarLoad)
}

我相信这是没有效率的,但我不知道如何以任何其他方式。

为了得到我的最终结果,我使用了一个外部函数;

代码语言:javascript
运行
复制
Results <- outer(1:nrow(Unique_Substations), 1:2, Vectorize(GetMax))

在我的示例中,所有这些数据帧都要大得多(每行40000行左右),因此我确实需要对所涉及的函数进行一些良好的优化。我试着想出将函数向量化的方法,但是我想不出来。任何帮助都将不胜感激。

编辑:

现在我已经完全理解了被接受的awnser,我还有另一个问题。我的实际Customer_Information为188行,实际HouseHoldLoad为53k行。不用说,这并不是很好的merge()。对于这个问题,还有另一种不需要merge()或太慢的循环的解决方案吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-08-28 11:51:56

第一:生成随机数据时的set.seed()!在为这些结果编写代码之前,我做了set.seed(1000)

我认为一点merge,-ing和dplyr可以在这里有所帮助。首先,我们将数据变得更好:

代码语言:javascript
运行
复制
library(dplyr)
library(reshape2)

HouseHoldLoad <- melt(HouseHoldLoad, value.name="Load") %>% 
  select(HouseHoldType=variable, Load) %>% 
  mutate(HouseHoldType=gsub("Type", "", HouseHoldType))

Solar_Panels <- melt(Solar_Panels, id.vars="Customer", 
                     value.name="SPYearVal") %>%
  select(Customer, SolarPanelYear=variable, SPYearVal) %>%
  mutate(SolarPanelYear=gsub("SolarPanelYear", "", SolarPanelYear))

dat <- merge(Customer_Information, Solar_Panels, by="Customer")

这使我们:

代码语言:javascript
运行
复制
##    Customer SubSt_Nm HouseHoldType SolarPanelYear SPYearVal
## 1      1001     SubB             1              1        16
## 2      1001     SubB             1              2        18
## 3      1001     SubB             1              2        16
## 4      1001     SubB             1              1        20
## 5      1002     SubD             2              1        16
## 6      1002     SubD             2              1        13
## 7      1002     SubD             2              2        20
## 8      1002     SubD             2              2        18
## 9      1003     SubA             1              2        15
## 10     1003     SubA             1              1        16
## 11     1005     SubC             2              2        19
## 12     1005     SubC             2              1        10
## 13     1006     SubA             1              1        15
## 14     1006     SubA             1              2        19
## 15     1007     SubC             1              1        17
## 16     1007     SubC             1              2        19
## 17     1009     SubA             1              1        10
## 18     1009     SubA             1              1        18
## 19     1009     SubA             1              2        18
## 20     1009     SubA             1              2        18

现在我们只是分组总结:

代码语言:javascript
运行
复制
dat %>% group_by(SubSt_Nm, SolarPanelYear) %>% 
  summarise(mx=max(sum(SPYearVal)*SolarLoad))

##   SubSt_Nm SolarPanelYear  mx
## 1     SubA              1 295
## 2     SubA              2 350
## 3     SubB              1 180
## 4     SubB              2 170
## 5     SubC              1 135
## 6     SubC              2 190
## 7     SubD              1 145
## 8     SubD              2 190

如果您使用data.table vs数据帧,即使使用40K条目,它也应该非常快速。

更新给那些不能安装dplyr的人,这只是使用reshape2 (希望这是可安装的)

代码语言:javascript
运行
复制
library(reshape2)

HouseHoldLoad <- melt(HouseHoldLoad, value.name="Load")
colnames(HouseHoldLoad) <- c("HouseHoldType", "Load")
HouseHoldLoad$HouseHoldType <- gsub("Type", "", HouseHoldLoad$HouseHoldType)

Solar_Panels <- melt(Solar_Panels, id.vars="Customer", value.name="SPYearVal")
colnames(Solar_Panels) <- c("Customer", "SolarPanelYear", "SPYearVal")
Solar_Panels$SolarPanelYear <- gsub("SolarPanelYear", "", Solar_Panels$SolarPanelYear)

dat <- merge(Customer_Information, Solar_Panels, by="Customer")

rbind(by(dat, list(dat$SubSt_Nm, dat$SolarPanelYear), function(x) {
  mx <- max(sum(x$SPYearVal) * SolarLoad)
}))

##        1   2
## SubA 295 350
## SubB 180 170
## SubC 135 190
## SubD 145 190

如果您甚至连reshape2都不能安装,那么这只适用于基本的stats包:

代码语言:javascript
运行
复制
colnames(HouseHoldLoad) <- c("Load.1", "Load.2")
HouseHoldLoad <- reshape(HouseHoldLoad, varying=c("Load.1", "Load.2"), direction="long", timevar="HouseHoldType")[1:2]

colnames(Solar_Panels) <- c("Customer", "SolarPanelYear.1", "SolarPanelYear.2")
Solar_Panels <- reshape(Solar_Panels, varying=c("SolarPanelYear.1", "SolarPanelYear.2"), direction="long", timevar="SolarPanelYear")[1:2]
colnames(Solar_Panels) <- c("Customer", "SPYearVal")
Solar_Panels$SolarPanelYear <- gsub("^[0-9]+\\.", "", rownames(Solar_Panels))

dat <- merge(Customer_Information, Solar_Panels, by="Customer")

rbind(by(dat, list(dat$SubSt_Nm, dat$SolarPanelYear), function(x) {
  mx <- max(sum(x$SPYearVal) * SolarLoad)
}))

##        1   2
## SubA 295 350
## SubB 180 170
## SubC 135 190
## SubD 145 190
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25545194

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档