在R中使用空值转置和过滤Dataframe

时间:2014-06-04 17:36:33

标签: r

这个几乎是一个挑战!

我有以下数据框:

tag     hour                    val
N1      2013-01-01 00:00:00     0.3404266179
N1      2013-01-01 01:00:00     0.3274182995
N1      2013-01-01 02:00:00     0.3142598749
N2      2013-01-01 02:00:00     0.3189924887
N2      2013-01-01 04:00:00     0.3170907762
N3      2013-01-01 05:00:00     0.3161910788
N3      2013-01-01 06:00:00     0.4247638954

我需要把它变成这样的东西:

hour                    N1              N2              N3
2013-01-01 00:00:00     0.3404266179    NULL            NULL
2013-01-01 01:00:00     0.3274182995    NULL            NULL
2013-01-01 02:00:00     0.3142598749    0.3189924887    NULL
2013-01-01 03:00:00     NULL            NULL            NULL
2013-01-01 04:00:00     NULL            0.3170907762    NULL
2013-01-01 05:00:00     NULL            NULL            0.3161910788
2013-01-01 06:00:00     NULL            NULL            0.4247638954

由于事情并不那么容易,我的数据框架达到N5000,每小时有近200,000个条目。

时间戳表现得非常好,因为它可以通过简单的命令strptime("2013-01-01 00:00:00", "%Y-%m-%d %H:%M:%S") + c(0:172800)*60(172800分钟~4个月)生成所有时间戳的方式逐步增加每个人。但不一定你有每个时间戳的数据,正如我在示例中所示。

我知道我可以编写一个带有无限循环的函数,但是有没有办法只使用R(及其包)函数来做到这一点?

谢谢!

3 个答案:

答案 0 :(得分:3)

你想使用" reshape2"包:

 install.packages("reshape2")
 library(reshape2)
 newdf <- dcast(mydata, hour~tag)

reshape2是一个非常强大的软件包,我完全无法理解......但有时它有很好的有用的东西,只是工作。 : - )

更新:那是&#34; dcast&#34;不是&#34;演员&#34; ...我错误地使用了&#34;重塑&#34;不是&#34; reshape2&#34;包。固定!

答案 1 :(得分:2)

这既不是最直接也不优雅的解决方案,但它有效:

示例data.frame:

df <- data.frame(tag=rep(c("N1", "N2", "N4"), c(3,2,2)),
                 hour=structure(c(1,2,3,3,5,6,7), class="POSIXct"),
                 val=runif(7))
##   tag                hour       val
## 1  N1 1970-01-01 01:00:01 0.6645598
## 2  N1 1970-01-01 01:00:02 0.7924186
## 3  N1 1970-01-01 01:00:03 0.3813311
## 4  N2 1970-01-01 01:00:03 0.8555780
## 5  N2 1970-01-01 01:00:05 0.4480540
## 6  N4 1970-01-01 01:00:06 0.1875233
## 7  N4 1970-01-01 01:00:07 0.5755332

现在我们创建生成的date列(它只是一个示例):

uh <- structure(1:7, class="POSIXct") # or e.g. uh <- unique(df$hour), or seq(), etc.

然后我们创建一个&#34;空&#34;结果数据帧(每个val将为NA)

nr <- length(uh) # number of rows on out
# column definitions:
(coldef <- paste("hour=uh", paste(unique(df$tag), "NA_real_", sep="=", collapse=", "), sep=", "))
## [1] "hour=uh, N1=NA_real_, N2=NA_real_, N4=NA_real_"
# create output df:
outdf <- eval(parse(text=sprintf("data.frame(list(%s))", coldef)))

最后,让我们在每个N*列中设置值:

for (idx in split(1:nrow(df), df$tag))
   outdf[outdf$hour %in% df$hour[idx], as.character(df$tag[idx[1]])] <- df$val[idx]

答案 2 :(得分:2)

如果您不想打扰其他软件包,也可以考虑基本函数reshape。使用@ gagolews的样本数据

> reshape(df, idvar="hour", timevar="tag", v.names="val", direction="wide")
                 hour    val.N1    val.N2    val.N4
1 1969-12-31 19:00:01 0.8156553        NA        NA
2 1969-12-31 19:00:02 0.9203821        NA        NA
3 1969-12-31 19:00:03 0.8127614 0.7386737        NA
5 1969-12-31 19:00:05        NA 0.9648562        NA
6 1969-12-31 19:00:06        NA        NA 0.2540216
7 1969-12-31 19:00:07        NA        NA 0.5024042