将大型大型数据(1982年专栏)融合成一个长形式,然后将其有效地转换为R中的宽泛形式

时间:2015-01-08 02:43:11

标签: sql r data.table dplyr

我的数据集格式如下df

# the original data format
df <- data.frame(id = 1:2,
       var1.20130101 = 1:2,
       var1.20130102 = 6:7,
       var2.20130101 = c(NA,1),
       var2.20130102 = NA)
df

# id var1.20130101 var1.20130102 var2.20130101 var2.20130102
# 1             1             6            NA            NA
# 2             2             7             1            NA

我想要的最终输出是:

df.out <- data.frame(id = c(1, 1, 2, 2),
                     date = c(20130101, 20130102),
                     var1 = c(1, 6, 2, 7),
                     var2 = c(NA, NA, 1, NA))
df.out
# id     date var1 var2
# 1 20130101    1   NA
# 1 20130102    6   NA
# 2 20130101    2    1
# 2 20130102    7   NA

希望这能解释我想要执行的实际操作。


实际上,我必须在24个CSV文件上执行此任务。每个文件中有大约1982列(和几千行)。

  1. id列,
  2. id列和
  3. 对应的列名称
  4. 22个变量与三个月日期相结合(=> 22 * 90 = 1980列)。
  5. 这是我的工作流程:

    1. 读取数据(read.tablefread()无法读取原始文件)并将每个文件拆分为3个子文件,每个子文件大约450MB。
    2. 对于每个子文件,请使用fread()melt()来阅读。
    3. 然后从列名称中提取日期和名称信息。
    4. {li> dcast() id ~ date + name
    5. 将文件写回CSV文件。
    6. 这是我正在使用的脚本。我正在寻找更高效和自动化(不分割文件)的解决方案。

      setwd("C:/Users/Administrator/Desktop/chencheng/rawdata")
        source("code1.2.R")
        file.name <- list.files()
        n <- length(file.name)
        for (i in 1:n){
          fileDispart(file.name[i])
          gc(TRUE)
        }
        setwd("E:/chencheng/step2file")
        file.name2 <- list.files()
        n <- length(file.name2)
        for (i in 1:n){
          dataTran(file.name2[i])
          gc(TRUE)
        }
      

      code1.2.R:

      library(reshape2)
      library(stringr)
      library(data.table)
      library(dplyr)
      
      fileDispart <- function(file){
        dat <- read.csv(file)
        n <- dim(dat)[1]
        unit <- 120000
        m <- ceiling(n / unit)
        start <- 1
        file <- gsub('.csv', '', file)
        ####################################
        for(i in 1:m) {
          if(i < m) {
            end <- i * unit
            start <- end + 1
            write.csv(dat[start:end, ], paste0(file, i, '.csv'), 
                        quote = F, row.names = F, na = "")
          } else {
            write.csv(dat[start:n, ], paste0("E:/chencheng/step2file/", 
               file, "_", i, '.csv'), quote = F, row.names = F, na = "")
          }
        }
      }
      
      
      dataTran <- function(pathin = "") {
        pathout = "E:/chencheng/"
        # dat <- fread("e:/chencheng/step2file/2013Q1p2_3.csv")
        if(length(pathin) == 0 | length(pathout) == 0) stop("Wrong parameters!")
        dat <- fread(pathin)
        n <- dim(dat)[2]
        dat <- dat %>% select(-2) # remove the extra column, 
                                  # just chinese names of the id
        dat.m <- melt(dat, id = 1)
        rm(dat)
        gc()
        name <- as.character(dat.m$variable)
        name.len <-  nchar(name)
        dat.m$name <- str_sub(name, 1, name.len - 8)
        dat.m$date <- str_sub(name, name.len - 7, name.len)
        names(dat.m)[1] <- 'id'
        dat.m <- dat.m %>% select(-2) 
        dat.m <- dcast.data.table(dat.m, id + date ~ name, identity)
        # write the file
        filename <- gsub('.csv', '', pathin)
        write.csv(dat.m, paste0(pathout, filename, '.csv'), 
                  quote = F, row.names = F, na = "")
      }
      

      此外,我使用的服务器是64G RAM(Windows Server 2008)。 R和SQL服务器是我执行此任务的唯一两个选项;也许有点蟒蛇很好。

1 个答案:

答案 0 :(得分:0)

如果没有数据样本,很难解决这个问题,但应该可以进行一些明显的优化。
不确定它是否加速很多,但你可以尝试不存储中间数据并使用data.table链接

dataTran <- function(pathin = ""){
    # ...
    dat.m <- fread(pathin)[,-2L,with=FALSE
                           ][,melt(.SD, id=1:2, measure=3)]
    # ...
    # likely the following are redundant: rm(dat); gc()
    # ...
    # as.character, nchar, str_sub - likely those can be also speedup
    # ...
    filename <- gsub('.csv', '', pathin)
    dat.m[,-2L,with=FALSE
          ][,dcast.data.table(.SD, id + date ~ name, identity)
            ][,write.csv(.SD, paste0(pathout, filename, '.csv'), quote = F, row.names = F, na = "")]
}