迭代R数据框中的列名以更改其类型

时间:2015-07-13 23:47:51

标签: r

library(lubridate)

# data to build the df
d1 <- c("1/2/14", "3/5/15", "1/13/11") #start
d2 <- c("1/2/15", "4/5/15", "6/18/15") #stop
d3 <- c("5/16/08", "1/7/07", "6/22/01") #start
d4 <- c("11/29/12", "8/5/14", "1/13/12") #stop
a <- c("Blah", "Blah", "Blah")
b <- c("Blah", "Blah", "Blah")
c <- c("Blah", "Blah", "Blah")
f <- c("Blah", "Blah", "Blah")
colNames <- c("Col.a", "Col.b", "Col.c", "Project1.start", "Project1.end", "Project2.start", "Project2.end", "Col.f")

# assemble the df
df <- data.frame(a,b,c,d1,d2,d3,d4,f)
names(df) <- colNames

# change the char cols for dX into POSIX date objects to play nicely with    
# lubridate
df$Project1.start <- mdy(df$Project1.start)
df$Project1.end <- mdy(df$Project1.end)
df$Project2.start <- mdy(df$Project2.start)
df$Project2.end <- mdy(df$Project2.end)

BUT!我想在我指定的dX上迭代地执行上面的mdy。 想象一下,我没有d1-d4而是d1-d142。一定要优雅, 即,非暴力的方式这样做!

所以,我试过这个。我知道我在太多列上做mdy,但我只是想让它完全正常工作。我已尝试使用seq()等循环,但我知道 我错过了R所期望的基于矢量的方法。

f <- function(x) {x <- mdy(x)}
newdf <- apply(df,2,f)

但它会抛出

Warning messages:
1: All formats failed to parse. No formats found. 
...
10: All formats failed to parse. No formats found. 

并且newdf很糟糕:

     Col.a Col.b Col.c Project1.start Project1.end Project2.start Project2.end Col.f
[1,]    NA    NA    NA             NA           NA             NA           NA    NA
[2,]    NA    NA    NA             NA           NA             NA           NA    NA
[3,]    NA    NA    NA             NA           NA             NA           NA    NA

       Project1.duration Project2.duration
[1,]                NA                NA
[2,]                NA                NA
[3,]                NA                NA

我在做什么就是这么st00pid?

所以,一旦完成,我们想做一些日期数学

df$Project1.duration <- (df$Project1.end - df$Project1.start )
df$Project2.duration <- (df$Project2.end - df$Project2.start )

在这里。我希望能够迭代所有dX列的所有持续时间,但也许我需要重新整形数据才能实现这一点。如何为所有这些单独编码的不同项目花费大量的持续时间,并将它们重新组合成df,以便我可以为每个项目制作不同持续时间的图。在我的示例中,我有三个不同的持续时间,即行1:3,以便能够比较每个项目的行。

1 个答案:

答案 0 :(得分:5)

您的错误是因为apply正在将mdy应用于df的每个列的,而不仅仅是&#34; ProjectX。{start,end }&#34;那些。而且因为df[col]data.framemdy需要矢量 - 请尝试df[[col]]

e.g。

cols <- grep('Project', names(df))
# do a one-liner like this
df[cols] <- lapply(df[cols], mdy)
# or a loop like this if you want
for (col in cols) {
    df[[col]] <- mdy(df[[col]])
}

关于计算每个项目数据(如持续时间),你可以这样做:

projects <- paste0('Project', 1:2) # however many projects
df[paste0(projects, '.duration')] <- df[paste0(projects, '.end')] - df[paste0(projects, '.start')]

但是从长远来看(特别是如果你有很多项目或想要计算每个项目的大量统计数据,而不仅仅是持续时间),你可以考虑以长格式存储数据,即

Project  start  end duration
 1       ...
 1
 1
 2
 2
 2

(可能带有某种ID变量,因此您知道哪个项目2与哪个项目1相关)

然后您可以轻松地执行mydf$duration <- mydf$end - mydf$start,如果您想再次使用宽格式,则可以使用reshape