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


82

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

.jcall ( "RJavaTools", "Ljava / lang / Object;", "invokeMethod", cl, :
java.lang.OutOfMemoryError : Java 힙 공간에 오류가 있습니다.

.jcall ( "RJavaTools", "Ljava / lang / Object;", "newInstance", .jfindClass (class), :
java.lang.OutOfMemoryError : GC 오버 헤드 제한 초과

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

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

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

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

답변:


78

이것은 알려진 문제입니다. 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
  )
}

38
이 모든 문제는 이제 xlsx패키지를 Java openxlsxRcpp아닌 종속 된 패키지 로 교체하여 회피 할 수 있습니다 .
Richie Cotton

4
readxl유망 해 보이는 또 다른 새로운 C / C ++ 대안입니다.
Richie Cotton

1
불행하게도 나는 그 모두 감지하고 날짜를 읽기위한 매우 정크입니다 발견했습니다 - 모두 엑셀 날짜 형식 인 구제 불능 혼란에 결국 : \
MichaelChirico

2
@RichieCotton, 좋은 대안. 그러나 openxlsx는 .xls 또는 .xlm 파일을 읽을 수 없습니다! (2007 엑셀 파일 형식).
Espanta

전화를 options(java.parameters = "-Xmx8000m")로드하기 전에 rJava, xlsxjars, xlsx해결 Error in .jcall("RJavaTools", "Ljava/lang/Object;", "invokeMethod", cl, : org.apache.poi.POIXMLException: java.lang.reflect.InvocationTargetException Calls: getNetwork ... <Anonymous> -> .jrcall -> .jcall -> .jcheck -> .Call Execution haltedRHEL 6.3 x86_64의에서, 자바 1.7.0_79 (오라클), rJava_0.9-7, xlsxjars_0.6.0, xlsx_0.5.7
닉 동아

7

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

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

내 이전 for루프는 여전히 원래 jgc기능으로 어려움을 겪었 지만 추가 명령을 사용하면 더 이상 GC overhead limit exceeded오류 메시지가 표시 되지 않습니다 .


-1

행 단위로 쓰는 경우 루프 내에서 gc ()를 사용할 수도 있습니다. gc ()는 가비지 콜렉션을 의미합니다. gc ()는 메모리 문제의 모든 경우에 사용할 수 있습니다.


-1

위 오류에 대한 해결 방법 : 아래에 언급 된 r 코드를 사용하십시오.

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

그리고 파일을 다시 가져 오면 저에게 작동하므로 오류가 발생하지 않습니다.


두 가지 의견 : xlConnect에는 동일한 문제가 있습니다. 그리고 더 중요한 것은 누군가에게 다른 라이브러리를 사용하라고 말하는 것은 참조되는 라이브러리의 문제에 대한 해결책이 아닙니다. 여기서 목표는 xlsx 패키지 내에 머무르는 것입니다. XLConnect에 전념하는 다른 스레드가 있습니다.
Michael Tuchman

-1

읽는 대신 write.xlsx ()에 문제가 있었지만 실수로 32 비트 R을 실행했음을 깨달았습니다. 64 비트로 바꾸면 문제가 해결되었습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.