【问题标题】:How to write function to return plot but also an object (data.frame)?如何编写函数来返回绘图和对象(data.frame)?
【发布时间】:2021-06-10 14:29:32
【问题描述】:

描述和目标:在 R Studio 中,我想定义一个函数,如果给定 data.frame 的列包含过高份额的缺失值(由截止值定义),则该函数会删除该列百分比。此函数应返回有关子集 data.frame 的信息(剩余列数和缺失案例的剩余份额)以及子集 data.frame 本身以供进一步分析。此外,应该有一个选项可以使用同名包的函数vis_miss() 来可视化剩余的缺失案例。

使用的包:

library(tidyverse)
library(vismiss)

数据:

my.data <- tibble(col_1 = c(1:5),
                  col_2 = c(1,2,NA,NA,NA))

我的功能:

cut_cols <- function(df, na.perc.cutoff, vis_miss=FALSE) {
  df <- df[lapply(df, function(x) sum(is.na(x)) / length(x)) < na.perc.cutoff]
  cat(paste0("Remaining cols: ", ncol(df)),
      paste0("\nRemaining miss: ", paste0(round(sum(is.na(df)) / prod(dim(df)) * 100, 2), "%\n")))
  if (vis_miss==TRUE) {return(vis_miss(df[1:nrow(df),c(1:ncol(df))], warn_large_data=F))}
  df
}

测试:

cut_cols(my.data, 0.5, vis_miss = F) # without visualization
cut_cols(my.data, 0.5, vis_miss = T) # with visualization

问题: 正如您可能已经在上面的示例中看到的那样,只有第一行,vis_miss = F 实际上返回了 data.frame,而不是第二行,vis_miss = T。我假设这是因为额外的if () {} 子句,它返回一个绘图,然后结束该过程而不打印df。有没有办法防止这种情况发生,以便第一行也返回新的 data.frame?

【问题讨论】:

  • 您可以将结果包装在一个列表中:list(df, plot)

标签: r dataframe function


【解决方案1】:

您怀疑if(){} 子句阻止打印df 是正确的。我认为return() 阻止任何功能进一步运行。如果是这种情况,最好将其放在任何函数的末尾。

此外,使用print(df) 确保您的函数输出您的数据框。以下是对您的代码的一些更改

cut_cols <- function(df, na.perc.cutoff, vis_miss=FALSE) {
  df <- df[lapply(df, function(x) sum(is.na(x)) / length(x)) < na.perc.cutoff]
  cat(paste0("Remaining cols: ", ncol(df)),
      paste0("\nRemaining miss: ", paste0(round(sum(is.na(df)) / prod(dim(df)) * 100, 2), "%\n")))
  print(df)
  if (vis_miss==TRUE) {return(vis_miss(df[1:nrow(df),c(1:ncol(df))], warn_large_data=F))}
}

cut_cols(my.data, 0.5, vis_miss = T)

如果您感兴趣,这里还有一个选项。您可以将 df 和 plot 分配给一个列表,然后调用该列表。

cut_cols <- function(df, na.perc.cutoff, vis_miss=FALSE) {
  df <- df[lapply(df, function(x) sum(is.na(x)) / length(x)) < na.perc.cutoff]
  cat(paste0("Remaining cols: ", ncol(df)),
      paste0("\nRemaining miss: ", paste0(round(sum(is.na(df)) / prod(dim(df)) * 100, 2), "%\n")))

  # empty list
  list_ <- c()
  # assign df to first index of list
  list_[[1]] <- df

  if (vis_miss==TRUE){
    plot <- vis_miss(df[1:nrow(df),c(1:ncol(df))], warn_large_data=F)
    # assign plot to second index in list
    list_[[2]] <- plot
  }
  return(list_)
}

output <- cut_cols(my.data, 0.5, vis_miss = T)

调用output 将打印df 和绘图。 output[[1]] 将只打印 df。 output[[2]] 将只打印情节。

【讨论】:

  • 太棒了,谢谢!将 plot 和 df 存储在列表中会有什么好处?
  • 哦,我刚刚注意到cut_cols() -&gt; out 不再起作用,使用新函数(没有列表),可能是因为该函数只是“打印”而不将其作为对象返回以供进一步分析。 ..
  • @Fabian 的好处是能够将两者存储在一个对象中以供以后使用或打印。你的第二条评论是关于什么的?您是说将输出放入列表的函数不再打印了吗?
  • 我想在管道命令中使用它,目前看起来像这样(使用列表方法):cut_cols(my.data, 0.5) %&gt;% .[[1]] %&gt;% ... -&gt; new.data。那行得通。
  • 另一种方法的问题(不将其存储在列表中)是该函数不再输出 df 以供进一步分析,或者更准确地说,是我可以输入管道命令的 df。
猜你喜欢
  • 2013-02-02
  • 1970-01-01
  • 2020-05-06
  • 2018-04-17
  • 1970-01-01
  • 2019-11-04
  • 1970-01-01
  • 2020-01-03
  • 2022-01-17
相关资源
最近更新 更多