【问题标题】:How to get this dcast'able long table in R?如何在 R 中获得这个 dcast'able 长表?
【发布时间】:2017-05-23 10:06:49
【问题描述】:

我正在尝试在长表上应用dcast,继续线程答案How to get this data structure in R? 代码

dat.m <- structure(c(150L, 60L, 41L, 61L, 0L, 0L), .Dim = c(3L, 2L), .Dimnames = list(
    c("ave_max", "ave", "lepo"), NULL))
library("ggplot2")
library("data.table")
dat.m <- melt(as.data.table(dat.m, keep.rownames = "Vars"), id.vars = "Vars") # https://stackoverflow.com/a/44128640/54964
dat.m

print("New step")
# http://stackoverflow.com/a/44090815/54964
minmax <- dat.m[dat.m$Vars %in% c("ave_max","lepo"), ]
absol  <- dat.m[dat.m$Vars %in% c("ave"), ]
#minm   <- dcast(minmax, Vars ~ variable)
minm   <- dcast(minmax, Vars ~ ...)
absol <- merge(absol, minm, by = "Vars", all.x = T)

absol

#Test function    
ggplot(absol, aes(x = Vars, y = value, fill = variable)) +
       geom_bar(stat = "identity") +
       geom_errorbar(aes(ymin = lepo, ymax = ave_max), width = .25)

输出

dcast, melt

      Vars variable value
1: ave_max       V1   150
2:     ave       V1    60
3:    lepo       V1    41
4: ave_max       V2    61
5:     ave       V2     0
6:    lepo       V2     0
[1] "New step"
   Vars variable value V1 V2
1:  ave       V1    60 NA NA
2:  ave       V2     0 NA NA
Error in FUN(X[[i]], ...) : object 'lepo' not found
Calls: <Anonymous> ... by_layer -> f -> <Anonymous> -> f -> lapply -> FUN -> FUN
Execution halted

预期输出:通过测试函数ggplot

测试 Uwe 的提议

目的是得到这个数据结构

dat.m <- structure(c(150L, 60L, 41L, 61L, 0L, 0L), .Dim = c(3L, 2L), .Dimnames = list(c("ave_max", "ave", "lepo"), NULL)) 

来自这个数据结构

dat.m <- structure(list(ave_max = c(15L, 6L), ave = c(6L, NA), lepo = c(4L, NA)), .Names = c("ave_max", "ave", "lepo"), class = "data.frame", row.names = c(NA, -2L))

尝试

dat.m <- structure(list(ave_max = c(15L, 6L), ave = c(6L, NA), lepo = c(4L, NA)), .Names = c("ave_max", "ave", "lepo"), class = "data.frame", row.names = c(NA, -2L))

# ...
  1. 代码和输出

    dat.m <- setDT(dat.m)
    

    输出错误

            ave_max      ave      lepo
    1:           15        6         4
    2:            6       NA        NA
    Classes ‘data.table’ and 'data.frame':  2 obs. of  3 variables:
      $ ave_max: int  15 6
      $ ave    : int  6 NA
      $ lepo   : int  4 NA
      - attr(*, ".internal.selfref")=<externalptr> 
    
  2. 代码和输出

    dat.m <- as.matrix(dcast(melt(setDT(dat.m), measure.vars = names(dat.m)), variable ~ rowid(variable))[, variable := NULL]); 
    dimnames(dat.m) <- list(names(dat.m), NULL);
    

    输出错误

     Error in `:=`(variable, NULL) : 
    Check that is.data.table(DT) == TRUE. Otherwise, := and `:=`(...) are defined for use in j, once only and in particular ways. 
     See help(":=").
    

R:3.4.0(向后移植)
操作系统:Debian 8.7。

【问题讨论】:

  • 请删除对library("reshape2") 的调用,因为data.table 有自己的melt()dcast() 的快速实现。
  • 如果您 (1) 编辑 Q 的重要部分,(2) 对不同的对象使用相同的变量名称 dat.m,则很难回答您的问题。对于矩阵对象,最好使用 dat.m,对于 data.frame 对象,最好使用 dat.df。我在下面的答案已经过测试,可以产生给定数据所示的结果。

标签: r data-structures


【解决方案1】:

OP 已经编辑了他的问题,并将数据作为 data.frame 提供:

dat.df <- structure(list(ave_max = c(15L, 6L), ave = c(6L, NA), lepo = c(4L, NA)), 
                    .Names = c("ave_max", "ave", "lepo"), class = "data.frame", 
                    row.names = c(NA, -2L))

dat.df
#  ave_max ave lepo
#1      15   6    4
#2       6  NA   NA
class(dat.df)
#[1] "data.frame"

他现在要求将此 data.frame 转换为一个矩阵,该矩阵类似于 this answer 中用作输入数据的矩阵。

这可以通过使用data.table来实现:

library(data.table)   # CRAN version 1.10.4 used
# transpose the input data frame, use rowid() to create columns,
# remove a character column to ensure matrix will be of type integer,
# finally, coerce to matrix
dat.m2 <- as.matrix(
  data.table::dcast(
    data.table::melt(setDT(dat.df), measure.vars = names(dat.df)), 
    variable ~ rowid(variable)
  )[, variable := NULL]
)
# add row names, remove column names
dimnames(dat.m2) <- list(names(dat.df), NULL)

dat.m2
#        [,1] [,2]
#ave_max   15    6
#ave        6   NA
#lepo       4   NA

str(dat.m2)
# int [1:3, 1:2] 15 6 4 6 NA NA
# - attr(*, "dimnames")=List of 2
#  ..$ : chr [1:3] "ave_max" "ave" "lepo"
#  ..$ : NULL

class(dat.m2)
#[1] "matrix"

编辑:我已经修改了上面的代码以使用双冒号运算符来明确说明应该从中获取melt()dcast() 的命名空间。通常,这不是必需的,因为 data.table 已经加载。但是,OP 报告的问题可能是由于在 data.table 之后加载包 reshape2 引起的。 data.table 包拥有自己更快的 reshape2::dcast()reshape2::melt() 实现。当由于某种原因加载了两个包时,可能会发生名称冲突。

【讨论】:

  • 确保输入数据集是使用setDT()强制的data.table或data.frame。此外,我恭敬地建议披露您的各种问题的完整背景。例如,您引用的链接不是关于在函数中使用data.table,而是在作为包一部分的函数中使用。
  • 发现我的错误:library(reshape2) 在另一个函数中,使情况复杂化。也许,将来我应该开始使用一些 API 来限制此类事件;等等来说明哪些包在功能上是可以接受的。这可能吗?
  • 在可能的情况下,我更喜欢使用双冒号运算符,例如 stringr::str_replace() 而不是加载整个包,例如 library(stringr) 和代码中的其他位置 str_replace()。因此,写 data.table::melt()data.table::dcast() 可能会有所帮助,以防万一 library(reshape2) 已加载。
【解决方案2】:

OP 已将数据作为矩阵提供:

dat.m <- structure(c(150L, 60L, 41L, 61L, 0L, 0L), .Dim = c(3L, 2L), .Dimnames = list(
  c("ave_max", "ave", "lepo"), NULL))

#    dat.m
#        [,1] [,2]
#ave_max  150   61
#ave       60    0
#lepo      41    0
class(dat.m)
#[1] "matrix"

对于这个数据集,OP 希望使用 ggplot2 创建一个带有误差线的条形图,其中条形图的高度由 ave 的值给出,误差线的下限和上限为lepoave_max,分别在每一列中。

ggplot2 期望数据作为 data.frame 提供,因此需要转换数据。为此,使用了data.table

library(data.table)   # CRAN version 1.10.4 used

# convert to data.table & transpose
transposed <- dcast(melt(as.data.table(dat.m, keep.rownames = "Vars"), 
                         id.vars = "Vars"), variable ~ ...)
setnames(transposed, "variable", "Vars")

library(ggplot2)
ggplot(transposed, aes(x = Vars, y = ave, ymin = lepo, ymax = ave_max)) +
  geom_col() +
  geom_errorbar(width = .25)

【讨论】:

  • @LéoLéopoldHertz준영 试试dat.m2 &lt;- as.matrix(dcast(melt(setDT(dat.df), measure.vars = names(dat.df)), variable ~ rowid(variable))[, variable := NULL]); dimnames(dat.m2) &lt;- list(names(dat.df), NULL); dat.m2
  • @LéoLéopoldHertz준영 DT 是如何创建的?什么返回str(DT)
  • @LéoLéopoldHertz준영 您需要使用 setDT(dat.m) 将 data.frame 强制转换为 data.table。
猜你喜欢
  • 1970-01-01
  • 2013-08-19
  • 1970-01-01
  • 2020-05-04
  • 2013-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多