代码之家  ›  专栏  ›  技术社区  ›  jan-glx charlie

“tfread”是否存在?

  •  6
  • jan-glx charlie  · 技术社区  · 8 年前

    在里面 R 有没有一种有效的方法来读取转置的 .csv 文件

    例如,考虑以下文本文件:

    Name,Peter,Paul,Marry
    Age,40,9,38
    

    这可以理解为 data.table 使用以下有用的列类:

    library(data.table)    
    file <-  tempfile("tmp.txt")
    writeLines("Name,Peter,Paul,Mary\nAge,40,5,38\n", file)    
    
    lines <- readLines(file)
    lines <- lapply(lines, function(x) gsub(pattern=",", replacement="\n", x, fixed=TRUE))
    lines <- lapply(lines[-3], fread)
    do.call(cbind,lines)
    #>     Name Age
    #> 1: Peter  40
    #> 2:  Paul   5
    #> 3:  Mary  38
    

    有没有更简单的方法来实现这一点?是否有更高效的版本(我的文件是1 GB)?

    请注意,对于按列存储(如 数据桌子 .

    5 回复  |  直到 8 年前
        1
  •  3
  •   Onyambu    8 年前
    DT=setDT(read.table(text=do.call(paste,transpose(fread(file,h=F))),h=T,stringsAsFactors = F))
    DT
        Name Age
    1: Peter  40
    2:  Paul   5
    3:  Mary  38
    
    
    
    sapply(DT,class)
           Name         Age 
    "character"   "integer" 
    
        2
  •  3
  •   Clayton Stanley    8 年前

    这是@Dirk Eddelbuettel在评论中建议的方法的实现。

    > library(data.table)                                                                                                          
    > aTbl = fread("file.csv", colClasses="character", header=F)
    > aTbl
    
         V1    V2   V3   V4
    1: Name Peter Paul Mary
    2:  Age    40    5   38     
    
    > aTbl[, .SD
           ][, transpose(.SD)
           ][, setnames(.SD, .SD[1, t(.SD)])                                                                                                                   
           ][2:.N                                                                                                                  
           ][, fread(paste0(capture.output(write.csv(.SD, stdout(), row.names=F, quote=F)), collapse='\n'))                        
           ][, {bTbl <<- copy(.SD); .SD}                                                                                           
           ]  
    
        Name Age                                                                                                                   
    1: Peter  40                                                                                                                   
    2:  Paul   5                                                                                                                   
    3:  Mary  38  
    
    > lapply(bTbl, class)     
    
    $Name                                                                                                                          
    [1] "character"                                                                                                                
    
    $Age                                                                                                                           
    [1] "integer"                                                                                                                  
    
    > 
    
        3
  •  2
  •   jan-glx charlie    8 年前

    扩展@lmo的评论以使用 iotools :

      dt <- iotools::chunk.tapply(file(file, "rb"),  function(x) {
        fread(paste0(apply(iotools::mstrsplit(x, sep=","), 2, paste0, collapse = ","), collapse = "\n"))
      }, CH.MERGE = cbind)
    

    这比当前的其他解决方案更有效。

        4
  •  2
  •   Vaibhav Garg    8 年前

    不幸地 tfread 似乎不存在。

    拟定解决方案的时间安排 200 observations of 20000 character/integer variables / 20000 observations of 200 character/integer variables :

    1. readLines-fread (@jan-glx) :7秒/1.2秒
    2. fread - transpose - paste - read.table (@Onymambu) :8秒/36秒
    3. ll-within-j: fread - transpose - write.csv - paste - fread (@Clayton Stanley) :5分钟/12秒
    4. command line transpose- fread (@jan-glx) :2.4秒/1.6秒
    5. iotools-paste-paste-fread (@jan-glx) :1.4秒/1.2秒
    6. fread公司 - 转置 - type.convert (@弗兰克):4.2秒/3.6秒

    代码:

    library(data.table)    
    file <-  tempfile("tmp.txt")
    p <- 100 # = 200 lines/columns
    n <- 10000 # = 20000 values per line / rows
    writeLines(rep(c(paste("Name",paste0(rep(c("Peter","Paul"), n), collapse = ","), sep=","),
                     paste("Age",paste0(rep(c("40","5"), n), collapse = ","), sep=",")
                   ), p), file(file,"wb"))    
    
    system.time({ # 1
    lines <- readLines(file)
    lines <- lapply(lines, function(x) gsub(pattern=",", replacement="\n", x, fixed=TRUE))
    lines <- lapply(lines, fread)
    dt <- do.call(cbind,lines)
    dim(dt)
    })
    
    system.time({ # 2
    DT=setDT(read.table(text=do.call(paste,transpose(fread(file,h=F))),h=T,stringsAsFactors = F))
    dim(DT)
    })
    
    system.time({ # 3
    aTbl = fread(file, colClasses="character", header=F)
    invisible(
      aTbl[, .SD
           ][, transpose(.SD)
             ][, setnames(.SD, .SD[1, t(.SD)])                                                                                                                   
               ][2:.N                                                                                                                  
                 ][, fread(paste0(capture.output(write.csv(.SD, stdout(), row.names=F, quote=F)), collapse='\n'))                        
                   ][, {bTbl <<- copy(.SD); .SD}                                                                                           
                     ]  
    )
    dim(bTbl)
    })
    
    system.time({ # 4 wide
      dt <- fread(paste0("transpose -t -l 20005x205 --fsep , \"", file, "\""))
      dim(dt)
    })
    
    system.time({ # 4 long
    dt <- fread(paste0("transpose -t -l 205x20005 --fsep , \"", file, "\""))
    dim(dt)
    })
    
    system.time({ # 5
      infile <- file(file, "rb")
      df <- iotools::chunk.tapply(infile, function(x) {
        fread(paste0(apply(iotools::mstrsplit(x, sep=","), 2, paste0, collapse = ","), collapse = "\n"))
      }, CH.MERGE = cbind)
      dim(df)
    })
    
    system.time({ # 6
    d <-  fread(file, header=FALSE); 
    d <- d[, lapply(transpose(.SD[,-1]), type.convert)][, setnames(.SD, d[[1]])]
    dim(d)
    })
    
        5
  •  1
  •   jan-glx charlie    8 年前

    要使用命令行工具扩展@ngm的注释,请执行以下操作:

    1. 下载: transpose.c
    2. 编译: gcc transpose.c -o transpose
    3. 使用: fread(paste0("transpose -t -l 205x20005 --fsep , \"", file, "\""))

    这需要了解表格的大致大小,并需要单字符行结尾,即, \n . 这很不方便,但比其他解决方案更快。