【问题标题】:Transpose and Filter Dataframe with null values in R在 R 中转置和过滤具有空值的数据帧
【发布时间】:2014-06-05 02:35:40
【问题描述】:

这几乎是一个挑战!

我有以下数据框:

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,每小时每个 N 有近 200.000 个条目。

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

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

谢谢!

【问题讨论】:

  • 如果“val”中没有“0”,您可以看到类似xtabs(val ~ as.character(hour) + tag, DF) 的内容并将“0”替换为NA
  • 虽然我的数据框中确实有 0,但 xtabs 可以轻松做到这一点,但是太慢了!演员几乎是瞬间的!

标签: r


【解决方案1】:

你想使用“reshape2”包:

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

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

更新:那是“dcast”而不是“cast”......我错误地使用了“reshape”而不是“reshape2”包。已修复!

【讨论】:

  • 我可能错了,但不应该是dcast而不是cast吗?我尝试运行您的代码,但 R 找不到函数 cast,尽管 ?cast 将我带到 reshape2 帮助页面(已安装 reshape2)。 (它与dcast 配合得很好)
  • 你完全正确!你知道,我想我同时安装了“重塑”。立即编辑。
  • 简单到我都不好意思了!我真的应该更好地理解 reshape 的能力。正如你一样,我无法理解的大多数功能...... @beginneR,dcast 返回一个数据帧。 acast 返回一个数组/向量
【解决方案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.

然后我们创建一个“空”的结果数据框(每个 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* 列中设置 val:

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]

【讨论】:

    【解决方案3】:

    如果您不想打扰另一个包,您也可以考虑使用基本函数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
    

    【讨论】:

    • 对于一个小数据帧,它可以完美运行,但对于我的实际 df(1M 行),它显然是由于内存管理而崩溃的。
    猜你喜欢
    • 2022-01-22
    • 2021-10-24
    • 2021-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-05
    • 1970-01-01
    • 2020-03-08
    相关资源
    最近更新 更多