【问题标题】:Is is possible to convert a dataframe object to a tribble constructor?是否可以将数据框对象转换为 tribble 构造函数?
【发布时间】:2017-08-07 22:55:00
【问题描述】:

我的数据如下所示:

library(tidyverse)
df <- tibble(
    x = c(0, 179, 342, 467, 705, 878, 1080, 1209, 1458, 1639, 1805, 2000, 2121, 2339, 2462, 2676, 
      2857, 3049, 3227, 3403, 3583, 3651, 4009, 4034, 4151, 4194, 4512, 4523, 4679, 5789), 
    y = c(4.7005, 4.8598, 5.0876, 5.0938, 5.3891, 5.6095, 5.8777, 6.0064, 6.3063, 6.4723, 6.6053, 
          6.8145, 6.9078, 7.1701, 7.2633, 7.3865, 7.5766, 7.644, 7.8018, 7.9505, 8.0974, 8.1937, 
          8.2391, 8.294, 8.3143, 8.3452, 8.5092, 8.5172, 8.5993, 9.0275))

是否可以将我的数据框/tibble 对象转换为tribble“构造函数”?

我正在寻找类似 @​​987654327@ 的东西,但更轻量级并且专门用于数据帧。

【问题讨论】:

标签: r tidyverse


【解决方案1】:

在这个问题的previous version 发火后,我花了一些时间试图拼凑出我正在寻找的东西:

“mribble”函数(如 make tribble):

mribble <- function(df) {

    names <- colnames(df)
    names <- sapply("~", paste, names, sep = "")
    names <- as.character(names)
    names <- paste(names, collapse = ", ")
    names <- paste(names, ",\n", sep = "")

    rows <- NULL
    for(i in seq_along(1:nrow(df))) {
        r <- as.character(df[i,])
        r <- paste(r, collapse = ", ")
        r <- paste(r, ",\n", sep = "")
        rows <- c(rows, r)
    }

    last <- rows[length(rows)]
    rows <- rows[-length(rows)]
    last <- substr(last, 1, nchar(last)-3)
    rows <- c(rows, last)

    meat <- c(names, rows)
    meat <- paste(meat, collapse = "")

    bun <- paste("df <- tribble(\n", meat, ")", sep = "")

    cat(bun)
}

mribble(df)

这会将其打印到控制台:

df <- tribble(
    ~x, ~y,
    0, 4.7005,
    179, 4.8598,
    342, 5.0876,
    467, 5.0938,
    705, 5.3891,
    878, 5.6095,
    1080, 5.8777,
    1209, 6.0064,
    1458, 6.3063,
    1639, 6.4723,
    1805, 6.6053,
    2000, 6.8145,
    2121, 6.9078,
    2339, 7.1701,
    2462, 7.2633,
    2676, 7.3865,
    2857, 7.5766,
    3049, 7.644,
    3227, 7.8018,
    3403, 7.9505,
    3583, 8.0974,
    3651, 8.1937,
    4009, 8.2391,
    4034, 8.294,
    4151, 8.3143,
    4194, 8.3452,
    4512, 8.5092,
    4523, 8.5172,
    4679, 8.5993,
    5789, 9.027)

我的解决方案非常笨拙,不适用于字符。反馈将不胜感激。

【讨论】:

    【解决方案2】:

    我认为mc_tribble 是一个更好的名字,看起来你可以把它浓缩成:

    mc_tribble <- function(indf, indents = 4, mdformat = TRUE) {
      name <- as.character(substitute(indf))
      name <- name[length(name)]
    
      meat <- capture.output(write.csv(indf, quote = TRUE, row.names = FALSE))
      meat <- paste0(
        paste(rep(" ", indents), collapse = ""),
        c(paste(sprintf("~%s", names(indf)), collapse = ", "),
          meat[-1]))
    
      if (mdformat) meat <- paste0("    ", meat)
      obj <- paste(name, " <- tribble(\n", paste(meat, collapse = ",\n"), ")", sep = "")
      if (mdformat) cat(paste0("    ", obj)) else cat(obj)
    }
    

    试试看:

    short_iris <- head(iris)
    
    mc_tribble(short_iris)
    

    改进:

    • 短代码
    • 捕获“tibble”的名称
    • 有缩进参数
    • 有一个参数可以方便地添加 4 个空格以在 Stack Overflow 上粘贴
    • 听起来更好吃

    我已将此添加到my "SOfun" package。你可以安装它:

    source("http://news.mrdwab.com/install_github.R")
    install_github("mrdwab/overflow-mrdwab") # for writeClip -- plus it's awesome
    install_github("mrdwab/SOfun")
    

    用法很简单:

    library(SOfun)
    mc_tribble(short_iris)
    

    优点:

    • 现在将输出复制到剪贴板(如果您安装了“溢出”)
    • 比以前更实惠!

    【讨论】:

    • 这太棒了。您是否认为有一种方法可以轻松扩展它以保留列类型? (列z 有字符?)
    • @emehex,现在就试试吧。
    • 现在我们可以简要介绍一下什么是 tribble 吗?
    • 这太棒了@A5C1D2H2I1M1N2O1R2T1。我会向 alistaire 链接的 tidyverse 包提交 PR
    • @emehex,安装overflow,然后安装SOfun,您可以将它与library(SOfun); mc_tribble(iris) 一起使用:-)
    【解决方案3】:

    受@A5C1D2H2I1M1N2O1R2T1 的启发,我创建了一个更广泛的解决方案。它处理大多数标准列类型,包括字符、因子、整数、数字、逻辑和列表。对于第二个参数,它也采用dput 的语法,因此应该能够输出到文件、连接或(默认情况下)控制台。它也采用了dput的标准返回值作为它的输入,不可见。

    dput_to_var <- function(x) {
      con <- textConnection("out", "w", local = TRUE)
      dput(x, con)
      close(con)
      paste(out, collapse = "")
    }
    
    dput_tribble <- function(indf, file = "") {
      stopifnot(is.data.frame(indf))
      cols <- lapply(indf, function(col) {
        switch(class(col),
               factor =, character = paste0("\"", col, "\""),
               logical =, numeric =, integer = col,
               list = lapply(col, dput_to_var)
               )
      })
      meat <- c(paste(sprintf("~%s", names(indf)), collapse = ", "),
                do.call(paste, c(cols, sep = ", ")))
      out <- paste0("tribble(\n", paste(meat, collapse = ",\n"), ")")
      if (is.character(file)) {
        if (nzchar(file)) {
          file <- file(file, "wt")
          on.exit(close(file))
        } else {
          file <- stdout()
        }
      }
      writeLines(out, file)
      invisible(indf)
    }
    

    根据@alistaire 的建议,我已经forked the tibble package and added this。我发了pull request

    【讨论】:

      【解决方案4】:

      datapasta::dpasta() 应该是合适的。您的示例的输出:

      dpasta(df)
      tibble::tribble(
          ~x,     ~y,
           0, 4.7005,
         179, 4.8598,
         342, 5.0876,
         467, 5.0938,
         705, 5.3891,
         878, 5.6095,
        1080, 5.8777,
        1209, 6.0064,
        1458, 6.3063,
        1639, 6.4723,
        1805, 6.6053,
        2000, 6.8145,
        2121, 6.9078,
        2339, 7.1701,
        2462, 7.2633,
        2676, 7.3865,
        2857, 7.5766,
        3049,  7.644,
        3227, 7.8018,
        3403, 7.9505,
        3583, 8.0974,
        3651, 8.1937,
        4009, 8.2391,
        4034,  8.294,
        4151, 8.3143,
        4194, 8.3452,
        4512, 8.5092,
        4523, 8.5172,
        4679, 8.5993,
        5789, 9.0275
        )
      

      https://cran.r-project.org/web/packages/datapasta/index.html https://github.com/MilesMcBain/datapasta

      【讨论】:

        【解决方案5】:

        根据基里尔的comment here, 这现在是包的一部分:https://github.com/krlmlr/deparse,在函数 deparsec 中

        library(deparse)
        #> 
        #> Attaching package: 'deparse'
        #> The following object is masked from 'package:base':
        #> 
        #>     deparse
        library(tibble)
        
        # dataframe
        df <- tribble(
          ~a, ~b, ~c,
          1L, 0.1, "a"
        )
        
        # tribble script
        deparsec(df, as_tribble = TRUE)
        #> tribble(
        #>   ~a, ~b,  ~c, 
        #>   1L, 0.1, "a"
        #> )
        

        reprex package (v0.2.0) 于 2018 年 8 月 9 日创建。

        【讨论】:

        • 看起来deparse 不见了。
        • 不确定我是否理解 -- devtools::install_github("krlmlr/deparse") 仍在安装。
        • 哦,我错过了 Github 的链接。我刚看到它已经从 CRAN 上取下来了。
        猜你喜欢
        • 2023-03-14
        • 1970-01-01
        • 2021-05-09
        • 1970-01-01
        • 1970-01-01
        • 2018-01-29
        • 2014-11-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多