sách gpt4 ai đã đi

Phát triển data.frame theo cách hiệu quả về bộ nhớ

In lại Tác giả: IT Prince Thời gian cập nhật: 2023-10-28 23:28:32 35 4
mua khóa gpt4 Nike

theoTạo một khung dữ liệu R theo từng hàng ,sử dụng liên kết Đính kèm vào dữ liệu.khung Không lý tưởng vì nó tạo ra một bản sao của toàn bộ data.frame mỗi lần. Làm cách nào để R Tích lũy dữ liệu trong dữ liệu.khung Mà không phải chịu hình phạt này? Định dạng trung gian không cần phải là dữ liệu.khung.

1 Câu trả lời

Phương pháp đầu tiên

Tôi thử truy cập từng phần tử của data.frame được phân bổ trước:

res <- data.frame(x=rep(NA,1000), y=rep(NA,1000))
tracemem(res)
đối với (tôi trong 1:1000) {
res[i,"x"] <- runif(1)
res[i,"y"] <- rnorm(1)
}

Nhưng tracemem hoạt động không bình thường (ví dụ: data.frame được sao chép đến một địa chỉ mới mỗi lần).

Phương pháp thay thế (cũng không hiệu quả)

Một cách (không chắc là có nhanh hơn không vì tôi chưa đánh giá chuẩn) là tạo danh sách data.frames rồi đặt chúng vàochồng chấtCùng nhau:

makeRow <- hàm() dữ liệu.frame(x=runif(1),y=rnorm(1))
res <- replicate(1000, makeRow(), simply=FALSE ) # trả về danh sách các data.frames
thư viện(taRifx)
res.df <- ngăn xếp(res)

Thật không may, tôi nghĩ bạn sẽ gặp khó khăn trong việc phân bổ trước khi tạo danh sách. Ví dụ:

> tracemem(res)
[1] "<0x79b98b0>"
> res[[2]] <- dữ liệu.khung()
tracemem[0x79b98b0 -> 0x71da500]:

Nói cách khác, việc thay thế một phần tử trong danh sách sẽ khiến danh sách đó được sao chép. Tôi cho là toàn bộ danh sách, nhưng cũng có thể chỉ là phần tử đó trong danh sách. Tôi không rành lắm về cách quản lý bộ nhớ của R.

Có lẽ là cách tốt nhất

Cũng như nhiều quy trình bị hạn chế về tốc độ hoặc bộ nhớ hiện nay, cách tiếp cận tốt nhất có lẽ là sử dụng dữ liệu.bảng Còn hơn là dữ liệu.khung. bởi vì dữ liệu.bảng:= Toán tử gán, có thể cập nhật mà không cần sao chép lại:

thư viện(dữ liệu.bảng)
dt <- bảng dữ liệu(x=rep(0,1000), y=rep(0,1000))
tracemem(dt)
đối với (tôi trong 1:1000) {
dt[i,x := runif(1)]
dt[i,y := rnorm(1)]
}
# lưu ý không có tin nhắn từ tracemem

Nhưng như @MatthewDowle đã chỉ ra,bộ() là cách thích hợp để thực hiện điều này trong một vòng lặp. Sẽ nhanh hơn nếu làm thế này:

thư viện(dữ liệu.bảng)
n <- 10^6
dt <- bảng dữ liệu(x=rep(0,n), y=rep(0,n))

dt.colon <- hàm(dt) {
đối với (i trong 1:n) {
dt[i,x := runif(1)]
dt[i,y := rnorm(1)]
}
}

dt.set <- hàm(dt) {
đối với (i trong 1:n) {
đặt(dt,i,1L, runif(1) )
đặt(dt,i,2L, rnorm(1) )
}
}

thư viện (microbenchmark)
m <- microbenchmark(dt.colon(dt), dt.set(dt),times=2)

(Kết quả như sau)

Tiêu chuẩn

Chạy vòng lặp 10.000 lần, bảng dữ liệu sẽ nhanh hơn gần một cấp độ:

Đơn vị: giây
biểu thức min lq trung vị uq max
1 kiểm tra.df() 523.49057 523.49057 524.52408 525.55759 525.55759
2 kiểm tra.dt() 62.06398 62.06398 62.98622 63.90845 63.90845
3 kiểm tra. stack() 1196.30135 1196.30135 1258.79879 1321.29622 1321.29622

chuẩn mực

:=bộ() So sánh:

> nam
Đơn vị: mili giây
biểu thức min lq trung vị uq max
1 dt. dấu hai chấm(dt) 654.54996 654.54996 656.43429 658.3186 658.3186
2 dt.set(dt) 13.29612 13.29612 15.02891 16.7617 16.7617

Xin lưu ý rằng ở đây N Giá trị này là 10^6 thay vì 10^5, như thể hiện trong biểu đồ chuẩn ở trên. Do đó, khối lượng công việc tăng lên theo cấp số nhân và kết quả được đo bằng mili giây thay vì giây. Thực sự rất ấn tượng.

Liên quan đến r - phát triển data.frame theo cách hiệu quả về bộ nhớ, chúng tôi tìm thấy một câu hỏi tương tự trên Stack Overflow: https://stackoverflow.com/questions/11486369/

35 4 0
Giấy chứng nhận ICP Bắc Kinh số 000000
Hợp tác quảng cáo: 1813099741@qq.com 6ren.com