IT TIP

R에서 Excel로 쓸 때 java.lang.OutOfMemoryError 처리

itqueen 2020. 10. 12. 21:18
반응형

R에서 Excel로 쓸 때 java.lang.OutOfMemoryError 처리


xlsx패키지는 R에서 Excel 스프레드 시트를 읽고 쓰는 데 사용할 수 있습니다. 안타깝게도 중간 크기의 스프레드 시트에서도 java.lang.OutOfMemoryError발생할 수 있습니다. 특히,

## Error in .jcall("RJavaTools", "Ljava/lang/Object;", "invokeMethod", cl,  : 
##   java.lang.OutOfMemoryError: Java heap space  

## Error in .jcall("RJavaTools", "Ljava/lang/Object;", "newInstance", .jfindClass(class),  : 
##   java.lang.OutOfMemoryError: GC overhead limit exceeded 

(기타 관련 예외도 가능하지만 더 드뭅니다.)

스프레드 시트를 읽을 때이 오류와 관련하여 유사한 질문이있었습니다.

큰 xlsx 파일을 R로 가져 오시겠습니까?

CSV보다 Excel 스프레드 시트를 데이터 저장 매체로 사용할 때의 주요 이점은 동일한 파일에 여러 시트를 저장할 수 있다는 것입니다. 따라서 여기서는 워크 시트 당 하나의 데이터 프레임을 작성하는 데이터 프레임 목록을 고려합니다. 이 예제 데이터 세트에는 40 개의 데이터 프레임이 포함되어 있으며 각 프레임에는 최대 200,000 개의 행이있는 두 개의 열이 있습니다. 문제가 될만큼 충분히 크도록 설계되었지만 n_sheets및을 변경하여 크기를 변경할 수 있습니다 n_rows.

library(xlsx)
set.seed(19790801)
n_sheets <- 40
the_data <- replicate(
  n_sheets,
  {
    n_rows <- sample(2e5, 1)
    data.frame(
      x = runif(n_rows),
      y = sample(letters, n_rows, replace = TRUE)
    )
  },
  simplify = FALSE
)
names(the_data) <- paste("Sheet", seq_len(n_sheets))

이 파일을 기록하는 자연있어서 사용 통합 문서를 생성하는 createWorkbook각각의 데이터 프레임을 통해 호출 후, 루프 createSheetaddDataFrame. 마지막으로 통합 문서는 saveWorkbook. 루프가 어디로 넘어가는지 쉽게 볼 수 있도록 메시지를 루프에 추가했습니다.

wb <- createWorkbook()  
for(i in seq_along(the_data))
{
  message("Creating sheet", i)
  sheet <- createSheet(wb, sheetName = names(the_data)[i])
  message("Adding data frame", i)
  addDataFrame(the_data[[i]], sheet)
}
saveWorkbook(wb, "test.xlsx")  

8GB RAM이있는 시스템에서 64 비트로 GC overhead limit exceeded실행 addDataFrame하면 처음 실행하는 동안 오류가 발생 합니다.

을 사용하여 대용량 데이터 세트를 Excel 스프레드 시트에 어떻게 작성 xlsx합니까?


이것은 알려진 문제입니다. http://code.google.com/p/rexcel/issues/detail?id=33

해결되지 않은 동안 문제 페이지 패키지가로드 되기 전에 옵션 을 설정하여 힙 크기를 늘려야한다고 제안하는 Gabor Grothendieck 의 솔루션연결됩니다 . ( 의 종속성입니다 .)java.parametersrJavarJavaxlsx

options(java.parameters = "-Xmx1000m")

1000은 Java 힙을 허용하는 RAM의 MB 수입니다. 원하는 값으로 바꿀 수 있습니다. 이것에 대한 나의 실험은 더 큰 값이 더 낫다는 것을 시사하며 전체 RAM 권한을 행복하게 사용할 수 있습니다. 예를 들어 다음을 사용하여 최상의 결과를 얻었습니다.

options(java.parameters = "-Xmx8000m")

8GB RAM이있는 컴퓨터에서.

루프를 반복 할 때마다 가비지 콜렉션을 요청하여 추가 개선을 얻을 수 있습니다. @gjabel에서 언급했듯이 R 가비지 수집은 gc(). Java System.gc()메소드 를 호출하는 Java 가비지 콜렉션 함수를 정의 할 수 있습니다 .

jgc <- function()
{
  .jcall("java/lang/System", method = "gc")
}    

그런 다음 루프를 다음과 같이 업데이트 할 수 있습니다.

for(i in seq_along(the_data))
{
  gc()
  jgc()
  message("Creating sheet", i)
  sheet <- createSheet(wb, sheetName = names(the_data)[i])
  message("Adding data frame", i)
  addDataFrame(the_data[[i]], sheet)
}

이 두 코드 수정을 통해 코드는 i = 29오류가 발생하기 전까지 실행되었습니다 .

실패한 한 가지 기술 write.xlsx2은 각 반복에서 내용을 파일에 쓰는 데 사용 하는 것입니다. 이것은 다른 코드보다 느 렸고 10 번째 반복에서 넘어졌습니다 (하지만 적어도 내용의 일부가 파일에 기록되었습니다).

for(i in seq_along(the_data))
{
  message("Writing sheet", i)
  write.xlsx2(
    the_data[[i]], 
    "test.xlsx", 
    sheetName = names(the_data)[i], 
    append    = i > 1
  )
}

@ richie-cotton 답변을 바탕으로 기능에 추가 하면 CPU 사용량이 낮다 gc()것을 알았습니다 jgc.

jgc <- function()
{
  gc()
  .jcall("java/lang/System", method = "gc")
}    

My previous for loop still struggled with the original jgc function, but with extra command, I no longer run into GC overhead limit exceeded error message.


Solution for the above error: Please use the below mentioned r - code:

detach(package:xlsx) detach(package:XLConnect) library(openxlsx)

And, try to import the file again and you will not get any error as it works for me.


You can also use gc() inside the loop if you are writing row by row. gc() stands for garbage collection. gc() can be used in any case of memory issue.

참고URL : https://stackoverflow.com/questions/21937640/handling-java-lang-outofmemoryerror-when-writing-to-excel-from-r

반응형