【问题标题】:Dynamically create new columns in data.table在 data.table 中动态创建新列
【发布时间】:2017-09-16 20:06:21
【问题描述】:

我在 R 中有一个 data.table 并想创建一个新列。假设我将日期列名称保存为变量,并希望在新列中将 _year 附加到该名称。我可以通过仅指定名称来执行正常路由,但是如何使用 date_col 变量创建新的列名称。

这是我尝试过的。我想要的最后两个不起作用。

dat = data.table(one = 1:5, two = 1:5, 
                 order_date = lubridate::ymd("2015-01-01","2015-02-01","2015-03-01",
                           "2015-04-01","2015-05-01"))
dat
date_col = "order_date"
dat[,`:=`(OrderDate_year = substr(get(date_col)[!is.na(get(date_col))],1,4))][]
dat[,`:=`(new = substr(noquote(get(date_col))[!is.na(noquote(get(date_col)))],1,4))][]
dat[,`:=`(paste0(date_col, "_year", sep="") = substr(noquote(get(date_col))[!is.na(noquote(get(date_col)))],1,4))][]
dat[,`:=`(noquote(paste0(date_col, "_year", sep="")) = substr(noquote(get(date_col))[!is.na(noquote(get(date_col)))],1,4))][]

【问题讨论】:

    标签: r data.table


    【解决方案1】:

    最后两条语句返回错误信息:

    dat[,`:=`(paste0(date_col, "_year", sep="") = substr(noquote(get(date_col))[!is.na(noquote(get(date_col)))],1,4))][]
    
    Error: unexpected '=' in "dat[,`:=`(paste0(date_col, "_year", sep="") ="
    
    dat[,`:=`(noquote(paste0(date_col, "_year", sep="")) = substr(noquote(get(date_col))[!is.na(noquote(get(date_col)))],1,4))][]
    
    Error: unexpected '=' in "dat[,`:=`(noquote(paste0(date_col, "_year", sep="")) ="
    

    调用:=()函数的正确语法是:

    dat[, `:=`(paste0(date_col, "_year", sep = ""), 
               substr(noquote(get(date_col))[!is.na(noquote(get(date_col)))], 1, 4))][]
    dat[, `:=`(noquote(paste0(date_col, "_year", sep = "")), 
               substr(noquote(get(date_col))[!is.na(noquote(get(date_col)))], 1, 4))][]
    

    即,将= 替换为,


    但是,赋值语法和右手边太复杂了。

    order_date 列已经属于 Date 类:

    str(dat)
    
    Classes ‘data.table’ and 'data.frame':    5 obs. of  3 variables:
     $ one       : int  1 2 3 4 5
     $ two       : int  1 2 3 4 5
     $ order_date: Date, format: "2015-01-01" "2015-02-01" ...
     - attr(*, ".internal.selfref")=<externalptr>
    

    为了提取年份,可以使用year() 函数(来自data.table 包或lubridate 包中最后加载的任何内容),因此无需转换回字符并提取年份字符串必填:

    date_col = "order_date"
    dat[, paste0(date_col, "_year") := lapply(.SD, year), .SDcols = date_col][]
    
       one two order_date order_date_year
    1:   1   1 2015-01-01            2015
    2:   2   2 2015-02-01            2015
    3:   3   3 2015-03-01            2015
    4:   4   4 2015-04-01            2015
    5:   5   5 2015-05-01            2015
    

    或者,

    dat[, paste0(date_col, "_year") := year(get(date_col))][]
    dat[, `:=`(paste0(date_col, "_year"), year(get(date_col)))][]
    

    也可以。

    【讨论】:

      【解决方案2】:

      set 函数非常适合这样做。也比在 data.table 中设置更快。这就是你所追求的吗? http://brooksandrew.github.io/simpleblog/articles/advanced-data-table/#fast-looping-with-set

      library(data.table)
      dat = data.table(one = 1:5, two = 1:5, 
                       order_date = lubridate::ymd("2015-01-01","2015-02-01","2015-03-01",
                                 "2015-04-01","2015-05-01"))
      dat
      date_col = "order_date"
      
      year_col <- paste0(date_col, "_year", sep="")
      set(dat, j = year_col, value = substr(dat[[date_col]], 1, 4) )
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-04-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-08-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多