R-ohjelmointi.org

Tilastotieteellistä ohjelmointia R-kielellä

Objektin koon arvioiminen

Levylle tallennettujen suurikokoisten tiedostojen lukeminen R:ään on toisinaan arpapeliä, sillä tarkkaa muistin määrää on toisinaan hankala arvioida. Lisäksi tiedoston lukeminen kuluttaa enemmän muistia kuin tiedoston koon perusteella voisi olettaa. Hyvänä nyrkkisääntönä on, että tiedoston lukeminen R:ään vie noin kolme kertaa enemmän muistia kuin tiedoston koko on levyllä.

Löysin sattumalta myös näppärän funktion objektin koon arvioimiseen. Parantelemani versio osaa arvioida myös tekstimuotoisen aineiston koon:

predict_data_size = function(numeric_size, number_type = "numeric") {
  if(number_type == "integer") {
    byte_per_number = 4
  }
  if(number_type == "numeric") {
    byte_per_number = 8
  } 
  if(number_type == "character" & length(grep("1252", Sys.getlocale()))==1) {
    byte_per_number = 8
  }
  if(number_type == "character" & length(grep("1252", Sys.getlocale()))==1) {
    byte_per_number = 8
  }
  if(number_type == "character" & length(grep("UTF8", Sys.getlocale()))==1) {
    byte_per_number = 16
  }
  if(number_type == "character" & length(grep("UTF-16", Sys.getlocale()))==1) {
    byte_per_number = 16
  }
  if(number_type == "character" & length(grep("UTF-16LE", Sys.getlocale()))==1) {
    byte_per_number = 16
  }
  if(number_type == "character" & length(grep("UTF-32", Sys.getlocale()))==1) {
    byte_per_number = 32
  }
  if(number_type == "character" & length(grep("UTF-32LE", Sys.getlocale()))==1) {
    byte_per_number = 32
  }
  estimate_size_in_bytes = (numeric_size * byte_per_number)
  class(estimate_size_in_bytes) = "object_size"
  print(estimate_size_in_bytes, units = "auto")
}

Esimerkiksi 7400000 miljoonaa riviä ja 86 saraketta sisältävän objektin koko on n. 4,7Gb:tä:

predict_data_size(7400000*86)
4.7 Gb

Vastaavasti 7,4 miljoonaa riviä sisältävän tekstisarakkeen (leveys 15 merkkiä) koko on:

predict_data_size(7400000*15, "character")
846.9 Mb

Jos arvioitu tiedoston koko on suurempi kuin koneen keskusmuistin määrä, pitää aineisto lukea ja käsitellä osissa tai jollakin muulla sopivalla tavalla.

2 Responses to “Objektin koon arvioiminen”

  • Adippa sanoo:

    Moi.

    Tein seuraavan funktion:

    file_size = function(tiedosto,otos,rivit) {
    apu0=read.table(tiedosto,sep=”;”,header=TRUE,nrows=1)
    apu1=read.table(tiedosto,sep=”;”,header=TRUE,nrows=otos)
    apu2=object.size(apu1)
    apu3=object.size(apu0)
    estimate_size_in_bytes = ((apu2-apu3)/otos)*rivit
    class(estimate_size_in_bytes) = ”object_size”
    print(estimate_size_in_bytes, units = ”auto”)
    }
    file_size(”apu8.csv”,100,63965)

    Eli idea on lukea tiedosto sisään 1 rivisenä, lukea tiedostosta sisään otos eli n ensimmäistä riviä. Sitten lasketaan yhden tietueen keskimääräinen koko ja kerrotaan lopullisten tietueiden lukumäärällä. Ajattelin että yhden rivin tietueesta saa eräänlaisen sarakemetadatan ylläpidon kustannuksen.

    Ainakin tuolla 100 tietueen otoksella oli kohtuullisen lähellä oikeaa lopputulosta suhteessa siihen että oikea data sisälsi tuon 63965 riviä.

  • Jarno sanoo:

    @Adippa Kiitos, vaikuttaa oikein hyvältä funktiolta objektin empiirisen koon arviointiin. Mitä mieltä olet, olisiko funktio vielä näppärämpi, jos se laskisi tiedoston rivien lukumäärän automaattisesti sen sijaan, että rivimäärä on annettava sille syötteenä?