【问题标题】:String-transform vector-elements in data.framedata.frame 中的字符串转换向量元素
【发布时间】:2012-04-10 14:50:28
【问题描述】:

我有一个巨大的数据框df,在一列中有一个“年月”值,如下所示:“YYYYMM”。当前数据类型是数字。快照:

> df[[1]][1:10]
[1] 201001 201001 201001 201001 201001 201001 201001 201001 201001 201001
> str(df)
'data.frame':   2982393 obs. of  11 variables:
 $ YearMonth    : int  201001 201001 201001 201001 201001 201001 201001 201001 201001 201001 ...
 $ ...

我想要的是将此值转换为“YYYY-MM”形式的字符串(最终转换为因子),以便能够将其与其他数据帧进行比较。

我正在努力寻找一种简单的方法来转换价值。

我尝试使用as.Dateformat 函数。但是由于这些值没有任何天数,因此它不适用于字符串。使用 Numerics(与数据框列相同)我什至遇到了其他问题。

> as.Date("201001", format = "%Y%m")
 [1] NA

> as.Date(201001, format = "%Y%m")
 Error in as.Date.numeric(201001, format = "%Y%m") : 
    'origin' must be supplied
> as.Date(df[[1]], format = "%Y%m")
 Error in as.Date.numeric(df[[1]], format = "%Y%m") : 
    'origin' must be supplied

我只能转换一个值,使用subset 和字符串连接。 我写了下面的公式来处理一个元素:

transformString <- function( x ) { # x = value
    return ( paste(cbind(substring(x, 1, 4),"-",substring(x,5,6)), collapse = '') )
}

问题:除了遍历所有元素之外,我没有找到一种简单的方法将该函数应用于 data.frame 的整个列:

transformStringVector <- function( x ) { # x = vector
    for(i in 1:length(x)) {
       x[i]<-transformString(x[i])
    }
    return ( x )
}

这远非优雅且不利于性能。我尝试使用apply(见下文)和类似的东西,但遇到了错误......(我承认我并没有真正得到apply 功能)

> temp <- apply(df[[1]], 1, transformString )
Error in apply(df[[1]], 1, transformString ) : 
  dim(X) must have a positive length

在巨大的 data.frame 中,是否有人可以替代这种转换?或更笼统地说;对 data.frame 中的元素应用类似字符串的转换的简单方法?

【问题讨论】:

    标签: r dataframe


    【解决方案1】:

    原因

    > as.Date("201001", format = "%Y%m")
     [1] NA
    

    不起作用,是 R 日期需要一个日期组件。由于您的日期没有提供,因此您会得到一个缺失值。为了避免这种情况,只需添加一个 day 组件:

    R> x = c("201001","201102")
    R> x = paste(x, "01", sep="")
    

    所以我把所有的日期都定在了月初:

    R> y = as.Date(x, "%Y%m%d")
    [1] "2010-01-01" "2011-02-01"
    

    然后您可以使用format 来获得您想要的:

    R> format(y, "%Y-%m")
    [1] "2010-01" "2011-02"
    

    【讨论】:

      【解决方案2】:

      如果您只是想将列值转换为指定格式的字符串,而不关心 date 格式,substr()paste() 都将向量作为参数:

      xx<-c(201011,201003,201002,201010,201009,201005,201001,201001,201001,201001)
      
      paste(substr(xx,1,4),substr(xx,5,6),sep="-")
      # [1] "2010-11" "2010-03" "2010-02" "2010-10" "2010-09" "2010-05" "2010-01"
      # [8] "2010-01" "2010-01" "2010-01"
      

      这样就不用apply()

      【讨论】:

        【解决方案3】:

        要回答有关将其专门应用于 data.frame 的问题,您可以使用 $ 运算符访问该列。所以你可以使用这里提供的任何一个函数(我会使用 substr 变体)来做到这一点。如果您打算转换为因子,我会先这样做。

        > df <- data.frame(a=1:5,b=5:1,d=200101:200105)
        > df
          a b      d
        1 1 5 200101
        2 2 4 200102
        3 3 3 200103
        4 4 2 200104
        5 5 1 200105
        > #Convert to a factor now for performance reasons.
        > df$d <- as.factor(df$d)
        > df$d <- paste(substr(df$d, 1, 4), "-", substr(df$d, 5,6), sep="")
        > df
          a b       d
        1 1 5 2001-01
        2 2 4 2001-02
        3 3 3 2001-03
        4 4 2 2001-04
        5 5 1 2001-05
        
        > typeof(df$d)
        [1] "character"
        > df$d <- as.factor(df$d)
        > df
          a b       d
        1 1 5 2001-01
        2 2 4 2001-02
        3 3 3 2001-03
        4 4 2 2001-04
        5 5 1 2001-05
        > typeof(df$d)
        [1] "integer"
        

        请注意,根据您的 data.frame 的“巨大”程度,您可以先转换为因子,然后再将级别转换为连字符日期,从而获得更好的性能。

        > df <- data.frame(a=rep(1:5,1000000),b=rep(5:1,1000000),d=rep(200101:200105, 1000000))
        > nrow(df)
         [1] 5000000
        > # Hyphenate first
        > system.time(df$d <- paste(substr(df$d, 1, 4), "-", substr(df$d, 5,6), sep="")) + system.time(df$d <- as.factor(df$d))
          user  system elapsed 
          9.65    0.61   10.31 
        >
        > #Factor first
        > system.time(df$d <- as.factor(df$d)) + system.time(levels(df$d) <- paste(substr(levels(df$d), 1, 4), "-", substr(levels(df$d), 5,6), sep=""))
         user  system elapsed 
         0.68    0.25    0.93 
        

        因此,根据 data.frame 的属性,您可以通过先进行因式分解将性能提高 10 倍。

        附:如果您真的关心性能,则可以通过使用hash-backed factor 为您的因式分解代码(快速解决方案中最慢的部分)获得更好的属性。

        【讨论】:

        • 不错!这真的很有帮助!这让我对性能因素有了更深入的了解。谢谢!
        猜你喜欢
        • 1970-01-01
        • 2013-05-24
        • 2012-12-08
        • 1970-01-01
        相关资源
        最近更新 更多