2015-07-17 18 views
5

Tôi mới dùng R và cố gắng thay thế một số giá trị cho các vòng đấu giá từ gia đình áp dụng. tôi vẫn đừng hiểu hoàn toàn cách họ làm việc nhưng tôi cố gắng tạo ra một mảnh làm việc mã:trả lại nhiều giá trị từ sapply/lapply

#create some input data 
tech<-data.frame(cbind(c("p1","p2","p3","p4"),c(15,15,15,100),c(10,8,18,100))) 
colnames(tech)=c("id","capacity.el","capacity.th") 
tech$capacity.el<-as.numeric(tech$capacity.el) 
tech$capacity.th<-as.numeric(tech$capacity.th) 

heat<-data.frame(cbind(c(2,12,6,20,32,21,25,16,34,0),c(31,18,3,27,30,31,18,4,24,7),c(2,12,6,20,32,21,25,16,34,0),c(31,18,3,27,30,31,18,4,24,7))) 
colnames(heat)=c("p1","p2","p3","p4") 

> tech 
    id capacity.el capacity.th 
1 p1   2   1 
2 p2   2   4 
3 p3   2   3 
4 p4   1   2 


> heat 
    p1 p2 p3 p4 
1 2 31 2 31 
2 12 18 12 18 
3 6 3 6 3 
4 20 27 20 27 
5 32 30 32 30 
6 21 31 21 31 
7 25 18 25 18 
8 16 4 16 4 
9 34 24 34 24 
10 0 7 0 7 

#the result should be a matrix/list 
pel=matrix(,nrow=nrow(heat),ncol=ncol(heat)) 
epr=matrix(,nrow=nrow(heat),ncol=ncol(heat))   
result<-list() 

#main code  
result<-sapply(colnames(heat),function(x) { 
       a<-tech$capacity.th[match(x,tech$id)] 
       b<-tech$capacity.el[match(x,tech$id)] 
       sapply(heat[,x],function(y) { 
        pel<-a*y 
        return(pel) 
       }) 

       }) 

Ý tưởng là để "vòng lặp" thông qua các cột của "sức nóng" data.frame và thực hiện một số tính toán với giá trị từ dữ liệu "nhiệt". Vì lý do này, tôi sử dụng các fly sapply đầu tiên để có được các đặc tính tương ứng cho mỗi nhà máy trong bảng nhiệt từ bảng công nghệ. Thứ hai, sau đó thực hiện các phép tính . Kết quả "kết quả" là chính xác những gì tôi muốn.

Bây giờ tôi muốn tính toán nhiều hơn giá trị từ mỗi hàng trong "nhiệt" (pel và epr). Nhưng tôi không có ý tưởng làm thế nào để trích xuất các giá trị này từ bên trong các cuộc đấu giá thuận lợi. Tôi đã thử những điều sau đây với một danh sách nhưng điều này chiết xuất các giá trị như một ma trận lớn với 20 hàng. Kết quả hoàn hảo sẽ giống như danh sách có hai đối tượng ma trận hoặc data.frame, mỗi đối tượng có 10 hàng và 4 cột với giá trị pel/epr.

result<-sapply(colnames(heat),function(x) { 
       a<-tech$capacity.th[match(x,tech$id)] 
       b<-tech$capacity.el[match(x,tech$id)] 
       sapply(heat[,x],function(y) { 
        pel<-a*y 
        epr<-b*y 
       }) 
       new<-list(pel,epr) 
       return(new) 
       }) 

Tôi sẽ đánh giá cao bất kỳ trợ giúp hoặc nhận xét nào.

Trả lời

6

Tôi đề nghị bạn dọn dẹp dữ liệu của mình trước tiên. see the tidyr package for more information

Sau đó, bạn hợp nhất hai khung dữ liệu và bạn sẽ không cần bất kỳ vòng lặp nào hoặc * áp dụng các chức năng. Bạn chỉ cần làm phép tính của bạn trong vòng dataframe mới này, ví dụ bằng cách sử dụng các gói dplyr:

library(tidyr) 
library(dplyr) 

heat %>% 
    gather(id, value) %>% 
    left_join(tech, by="id") %>% 
    mutate(a = value * capacity.el, 
     b = value * capacity.th) 
+0

cảm ơn rất nhiều vì đề xuất của bạn. Tôi hiểu rằng không cần thiết trong trường hợp này để sử dụng chức năng * áp dụng. nhưng dữ liệu thực tế là 8760 hàng /> 300 cols và tôi sẽ phải thực hiện các phép tính phức tạp hơn so với phép nhân trong ví dụ – derdepe

+0

@derdepe Nếu dữ liệu của bạn được sắp xếp trong cơ sở dữ liệu thì thú vị hơn khi sử dụng dplyr. Vì các hoạt động được cung cấp bởi gói này sẽ chạy trực tiếp trên các bảng db. [xem dignr họa tiết] (https://cran.rstudio.com/web/packages/dplyr/vignettes/introduction.html). Ngoài ra gói này chứa rất nhiều chức năng tóm tắt và cửa sổ. – MarkusN

3
o <- match(tech$id,names(heat)); ## precompute tech row order to match heat column order 
ms <- names(tech[-1]); ## store multiplier column names from tech 
setNames(lapply(ms,function(m) t(t(heat)*tech[o,m])),ms); 
## $capacity.el 
##  p1 p2 p3 p4 
## [1,] 4 62 4 31 
## [2,] 24 36 24 18 
## [3,] 12 6 12 3 
## [4,] 40 54 40 27 
## [5,] 64 60 64 30 
## [6,] 42 62 42 31 
## [7,] 50 36 50 18 
## [8,] 32 8 32 4 
## [9,] 68 48 68 24 
## [10,] 0 14 0 7 
## 
## $capacity.th 
##  p1 p2 p3 p4 
## [1,] 2 124 6 62 
## [2,] 12 72 36 36 
## [3,] 6 12 18 6 
## [4,] 20 108 60 54 
## [5,] 32 120 96 60 
## [6,] 21 124 63 62 
## [7,] 25 72 75 36 
## [8,] 16 16 48 8 
## [9,] 34 96 102 48 
## [10,] 0 28 0 14 
+1

Rất tiếc, tôi không thấy câu trả lời của bạn, tôi sẽ xóa câu trả lời của tôi. –

2

Một lựa chọn có thể sử dụng data.table (tiếp cận tương tự như phương pháp dplyr @ user2992199 của). Chúng tôi chuyển đổi 'data.frame' thành 'data.table' (setDT(heat)), thay đổi từ định dạng 'rộng' sang 'dài' bằng melt, đặt khóa là 'id' (setkey(..., id)), kết hợp với 'công nghệ' và tạo các cột 'a' và 'b'.

library(data.table)#v1.9.5+ 
setkey(melt(setDT(heat), variable.name='id'), id)[tech 
    ][, c('a', 'b') := list(value*capacity.el, value*capacity.th)][] 
Các vấn đề liên quan