【问题标题】:Append suffix to column of entries in csv file (or in SQLite database)将后缀附加到 csv 文件(或 SQLite 数据库)中的条目列
【发布时间】:2011-05-04 04:14:30
【问题描述】:

我有一个相对较大的 csv 文件(1.2gb...比我的一台计算机上的 2gb RAM 大)。对于一列中的每个条目,我想附加“1C”,以便我可以加入/合并另一个数据框/数据库表。

如果文件不是那么大,使用read.csv 导入到data 然后使用data$symbol <- paste(data$symbol, "1C", sep="") 会很容易。但现在我收到了can't allocate vector of size x 警告。

scan() 这样的手动解决方案是我唯一的选择吗? (我有点害怕破坏我的数据)谢谢!

【问题讨论】:

    标签: r csv


    【解决方案1】:

    这有点难看,但是您可以逐行读取文件并将其逐行放入另一个文件中。这样你就永远不会把整个事情读入内存。这与 Joshua 的 awk 方法没有什么不同,而是使用 R(而且速度要慢得多)。下面的例子是我拼凑起来从 csv 中删除美元符号和百分号的例子。您可以更改中间的逻辑以执行您想要的逻辑。

    con  <- file(inputFile, open = "r")
    con2 <- file(temporaryFile, open = "w")
    
    while (length(oneLine <- readLines(con, n = 1, warn = FALSE)) > 0) {
        oneLine <- gsub("%", "", oneLine)     #strip out the percent signs
        oneLine <- gsub("\\$", "", oneLine)   #strip out the dollar signs
        cat(oneLine, file = con2, sep = "\n") #spit the line back out
      } 
    
    close(con)
    close(con2)
    

    【讨论】:

    • 您可以通过读取 .csv 文件的块来扩展它,并至少获得一些加速。
    【解决方案2】:

    如果您已经可以将数据导入 R,那么使用 scan 将无济于事。

    确保data 仅包含您需要合并的列,并在尝试您的paste 命令之前运行gc()(如果您接近内存限制的边缘,gc 会有所帮助)。

    如果失败,请查看this thread 中的一些解决方案。


    更新:
    如果你碰巧使用了 *nix,或者如果你在 Windows 上安装了 Rtools,你可以用gawk 来做这件事。如果您的数据在foo.csv 中,并且您想将“C1”添加到第二列,这将创建一个新文件bar.csv,并在第二列附加“C1”。

    compy: /home/josh
    > cat foo.csv 
    1,one,2,two
    3,three,4,four
    5,five,6,six
    
    compy: /home/josh
    > gawk -F "," '{OFS=","; $2=($2 "1C"); print}' < foo.csv > bar.csv
    
    compy: /home/josh
    > cat bar.csv 
    1,one1C,2,two
    3,three1C,4,four
    5,five1C,6,six
    

    这可能会比 R 更快,并且消耗的内存量可以忽略不计。

    【讨论】:

    • @Joshua -- 感谢您的链接!但是当我在 RAM 中获取整个 csv 之后,我没有足够的内存将 paste 恢复到自身(即使使用逐个元素的循环)。在我进行合并之前,我从包含我的数据的 SQLite db 中只选择了几列,所以那里没有内存问题。我宁愿在将 csv 添加到数据库之前附加“1C”,这样我就可以在那里执行 join 而不是 R 中的 merge。谢谢!
    • @Joshua -- 我在 Ubuntu 或 OSX 上,所以我会试试看!
    • @Joshua -- 谢谢!正是我想要的!我仍然是 linux 的小伙伴,所以我需要更多地研究这些基本工具!
    • @richardh 如果您将其引入 SQLite,是否有令人信服的理由不在 SQLite 中执行附加操作?
    • 是的,你明白了!执行 ||,然后索引,如果需要,然后加入。
    【解决方案3】:

    只读一列,我假设它可能是以后合并操作到内存中的主要唯一标识符:

    twocol <- read.table(file="what.csv", colClasses=("numeric", "character", rep("NULL", <number-of-remaining-columns>) , sep="," )
    twocol$V2 <- paste(twocol$V2, "1C", sep="")
    merge(twocol, otherdf, by.x="V1" , ....)
    

    【讨论】:

    • 谢谢!这与我正在做的事情相似。我的办公室电脑有点旧,无法处理前两行。 merge 很好,因为我在合并之前在 SQLite 中设置了子集,因此它合并的数据帧比原始 csv 文件小得多。
    【解决方案4】:

    将 1C 附加到第二列:

    perl -F, -lane '$F[1] .= "1C"; print join ",", @F' file.csv

    使用这些命令行选项:

    • -n 循环输入文件的每一行
    • -l 在处理之前删除换行符,然后将它们添加回
    • -a 自动拆分模式 - 将输入行拆分为 @F 数组。默认为空格分割。
    • -e执行perl代码
    • -F 自动拆分修饰符,在这种情况下拆分 ,

    @F 是每行中的单词数组,以$F[0] 开头的索引
    .= 是“附加到”运算符

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-15
      • 2019-08-17
      • 2013-08-03
      • 1970-01-01
      • 2021-07-21
      • 2020-07-11
      • 1970-01-01
      相关资源
      最近更新 更多