2010-06-24 49 views
2

我试图将一个列表和序列化每个项目,并将其放入一个CSV文件与一个密钥创建一个文本文件与键/值对。最终,这将通过Hadoop流式传输,所以在你问之前,我认为它确实需要放在一个文本文件中。 (但我对其他想法持开放态度)这一切看起来似乎非常直截了当。但我不能完全按照我想要的方式进行序列化(still)。R:从序列化对象中创建一个CSV

如果我这样做:

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

然后,我有那些讨厌的\ n后来搞砸了我的CSV解析。我可以进去用另外一些字符串替换\ n,我并不反对这样做。但是,这看起来有点混乱。

来考虑被省略rawToChar()调用,并抽生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文本文件的值!只有......我以后怎么把它变回原状?让我们来看看第一个十六进制元素: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的真数值)

关于如何破解这个螺母的任何想法?

+0

随机评论:你conisder使用RHIPE? http://www.stat.purdue.edu/~sguha/rhipe/ – mcpeterson 2010-06-24 22:32:13

+0

你用'writeBin'和'readBin'试过了吗? – nico 2010-06-25 06:07:03

+0

RHIPE看起来像一个非常整洁的项目。如果我有一个本地Hadoop集群,我可能会使用它。不过,我的流最终会进入Amzn EMR Hadoop引擎。 – 2010-06-25 11:57:21

回答

3

caToolsBase64编码器,解码器,您可以使用该软件包:

> library(caTools) 
> s<-base64encode(serialize("blah",NULL)) 
> s 
[1] "WAoAAAACAAIKAQACAwAAAAAQAAAAAQAAAAkAAAAEYmxhaA==" 
> unserialize(base64decode(s,"raw")) 
[1] "blah" 
+0

这看起来很有希望!将在今天上午进行测试。谢谢! – 2010-06-25 11:58:41

+0

我测试了它,它可以工作...但我有时会得到不完全匹配的结果。可能是一个浮点问题。我会在另一篇文章中提出这个具体问题。 – 2010-06-25 14:52:21

+0

后续问题在这里添加:http://stackoverflow.com/questions/3119037/r-serialize-base64-encode-decode-of-text-not-exactly-matching – 2010-06-25 16:59:26

0

也许你想as.raw(65)而不是65(十进制)为41(十六进制)

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

至于编码,您可以用Hadoop流中的二进制数据的工作?

+0

Hadoop可以使用二进制文件,但是从我能弄清楚的流模式需要文本。 – 2010-06-24 21:49:50

1

感谢jmoy为他的伟大的答案。我用他的建议,它很好。对于未来的搭便车者来说,我将离开我的功能,将列表转换为序列化的CSV文本文件,然后将它们重新转换为列表。我将这篇文章标记为社区wiki。随意编辑它,如果有更干净的方式做任何这些:

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) 
}