R: Создание CSV из сериализованных объектов - PullRequest
2 голосов
/ 25 июня 2010

Я пытаюсь взять список и сериализовать каждый элемент и поместить его в файл CSV с ключом для создания текстового файла с парами ключ / значение. В конечном итоге это будет проходить через потоковую передачу Hadoop, поэтому, прежде чем вы спросите, я думаю, что это действительно должно быть в текстовом файле. (но я открыт для других идей) Сначала все это казалось довольно простым. Но я не могу заставить сериализацию работать так, как я хочу ( все же ).

Если я сделаю это:

> rawToChar(serialize("blah", NULL, ascii=T))
[1] "A\n2\n133888\n131840\n16\n1\n9\n4\nblah\n"

Тогда у меня есть те надоедливые \ n, которые испортили мой CSV-анализ позже. Я мог бы пойти и заменить \ n другой строкой, что я не против делать. Однако это выглядит немного грязно.

Другая опция, которая пришла вам в голову, - это опустить вызов rawToChar () и перекачать raw ascii в текстовый файл:

> serialize("blah", NULL, ascii=T)
 [1] 41 0a 32 0a 31 33 33 38 38 38 0a 31 33 31 38 34 30 0a 31 36 0a 31 0a 39 0a
[26] 34 0a 62 6c 61 68 0a

Что ж, если я просто дам это в текстовый файл, я получу \ n после каждого элемента в списке. Поэтому я попытался немного вставить / свернуть:

> ser <- serialize("blah", NULL, ascii=T)
> ser2 <- paste(ser, collapse="")
> ser2
[1] "410a320a3133333838380a3133313834300a31360a310a390a340a626c61680a"

Теперь это значение, которое я могу записать в текстовый файл CSV! Только ... как мне потом снова превратить это в raw? Давайте просто возьмем первый шестнадцатеричный элемент: 41 Я даже не могу понять, как создать список необработанных элементов и вставить шестнадцатеричное значение 41 в один из элементов. Когда я пытаюсь поместить необработанное шестнадцатеричное значение в необработанный список, я получаю что-то вроде этого:

> r <- raw(1)
> r[1] <- 41
Error in r[1] <- 41 : 
  incompatible types (from double to raw) in subassignment type fix
> r[1] <- as.raw(41)
> r[1]
[1] 29 

Дерьмо! 29! = 41 (за исключением действительно больших значений 29 и действительно малых значений 41, конечно)

Есть идеи как взломать этот орех?

Ответы [ 3 ]

3 голосов
/ 25 июня 2010

Пакет caTools имеет кодировщик-декодер Base64 , который вы можете использовать:

> library(caTools)
> s<-base64encode(serialize("blah",NULL))
> s
[1] "WAoAAAACAAIKAQACAwAAAAAQAAAAAQAAAAkAAAAEYmxhaA=="
> unserialize(base64decode(s,"raw"))
[1] "blah"
1 голос
/ 25 июня 2010

спасибо jmoy за отличный ответ.Я использовал его рекомендации, и он прекрасно работает.Для будущих автостопщиков, которые попадают сюда, я оставляю свои функции для преобразования списка в сериализованные текстовые файлы CSV, а затем превращения их обратно в списки.Я отмечаю этот пост как сообщество вики.Не стесняйтесь редактировать его, если есть более чистый способ сделать это:

listToCsv <- function(inList, outFileName){
  require(caTools)
  if (is.list(inList) == F) 
        stop("listToCsv: The input list fails the is.list() check.")
  fileName <- outFileName
  cat("", file=fileName, append=F)

  i <- 1
  for (item in inList) {
    myLine <- paste(i, ",", base64encode(serialize(item, NULL, ascii=T)), "\n", sep="")
    cat(myLine, file=fileName, append=T) 
    i <- i+1
  }
}

csvToList <- function(inFileName){
  require(caTools)
  linesIn <- readLines(fileName, n=-1)
  outList <- NULL

  i <- 1
  for (line in linesIn){
    outList[[i]] <- unserialize(base64decode(strsplit(linesIn[[i]], split=",")[[1]][[2]], "raw"))
    i <- i+1
  }
  return(outList)
}
0 голосов
/ 25 июня 2010

Может быть, вы хотели as.raw(65) вместо 65 (в десятичном виде) 41 (в шестнадцатеричном)

 > as.hexmode(65)
[1] "41"

Что касается кодирования, можете ли вы работать с двоичными данными в потоковой передаче Hadoop?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...