【问题标题】:unexpected error when taking complementary set for data.frame in the list为列表中的 data.frame 获取补充集时出现意外错误
【发布时间】:2016-10-04 10:28:52
【问题描述】:

我在列表中有 data.frame 对象,我打算有条件地对 data.frame 对象执行 setdiff。我也提出了非常草图功能来完成这项任务,但是我在获取一组互补的 data.frame 时遇到了错误。特别是,我要取对应的data.frame取决于条件。任何人都可以向我提出任何有效解决此问题的想法吗?我怎样才能完成这项任务?

小例子:

myList <- list(
  saved = data.frame(from=c(3,33,54,91), to=c(23,42,71,107), label=c("a1","a4","a7","a11"), SC=c(22,6,13,7)),
  droped = data.frame(from=c(25,33,47,74,91), to=c(29,42,51,81,107), label=c("a2","a4","a6","a8","a11"), SC=c(3,6,4,5,7))
)

根据输入,我希望实现这个功能(只是草图):

library(dplyr)
func <- function(list, type=c("Bio", "Tech")) {
  type=match.arg(type)
  res <- ifelse(type=="Bio",
                res <- list[[1]],
                res <- setdiff(list[[1]], list[[2]]))
  return(res)
}

我收到这样的错误:

Error: not compatible: Factor levels not equal for column label

我想要的输出是:

如果类型是“生物”:

  from  to label SC
1    3  23    a1 22
2   33  42    a4  6
3   54  71    a7 13
4   91 107   a11  7

如果类型是“技术”:

 from  to label SC
1    3  23    a1 22
3   54  71    a7 13

谁能告诉我如何解决这个问题?如何更有效地获得预期输出?非常感谢。

【问题讨论】:

    标签: r list dataframe dplyr


    【解决方案1】:

    问题在于,每个数据框中的 label 列是一个因素,而不仅仅是字符。得到你想要的:

    myList <- list(
      saved = data.frame(from=c(3,33,54,91), to=c(23,42,71,107), label=c("a1","a4","a7","a11"), SC=c(22,6,13,7), stringsAsFactors=FALSE),
      droped = data.frame(from=c(25,33,47,74,91), to=c(29,42,51,81,107), label=c("a2","a4","a6","a8","a11"), SC=c(3,6,4,5,7), stringsAsFactors=FALSE)
    )
    
    func <- function(list, type=c("Bio", "Tech")) {
      type=match.arg(type)
      if(type=="Bio") list[[1]] else setdiff(list[[1]], list[[2]])
    }
    

    注意事项:

    1. 使用StringsAsFactors=FALSE 构建数据框。

    2. 另一个问题与您对func 的定义有关。在type 的标量比较上使用ifelse 只会返回结果的第一列。因此,请在您的 func 中使用 if-else

    有了这个:

    func(myList,"Bio")
    ##  from  to label SC
    ##1    3  23    a1 22
    ##2   33  42    a4  6
    ##3   54  71    a7 13
    ##4   91 107   a11  7
    func(myList,"Tech")
    ##  from to label SC
    ##1    3 23    a1 22
    ##2   54 71    a7 13
    

    如果您确实希望将 label 列保留为因子,则需要将这些因子的水平设置为各个因子水平的并集:

    ## This time with stringsAsFactors=TRUE
    myList <- list(
      saved = data.frame(from=c(3,33,54,91), to=c(23,42,71,107), label=c("a1","a4","a7","a11"), SC=c(22,6,13,7), stringsAsFactors=TRUE),
      droped = data.frame(from=c(25,33,47,74,91), to=c(29,42,51,81,107), label=c("a2","a4","a6","a8","a11"), SC=c(3,6,4,5,7), stringsAsFactors=TRUE)
    )
    
    myLevels <- unique(c(levels(myList[[1]]$label),levels(myList[[2]]$label)))
    ##[1] "a1"  "a11" "a4"  "a7"  "a2"  "a6"  "a8" 
    myList[[1]]$label <- factor(myList[[1]]$label,levels=myLevels)
    myList[[2]]$label <- factor(myList[[2]]$label,levels=myLevels)
    

    那么上面的func就和以前一样了。

    【讨论】:

    • 为什么不使用 ifelse?有什么原因吗?
    • @user88911:请查看我的编辑,看看我是否回答了这个问题。
    • 有什么建议可以让我的草图功能更加高效和兼容吗?谢谢你:)
    • @user88911:您无需在if-else(或ifelse)的主体内设置res 变量。此外,最后一个计算值总是从 R 中的函数返回,因此无需在末尾设置 res 然后再设置 return 它。在答案中查看我对func 的定义。
    • 感谢您的帮助 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-21
    • 1970-01-01
    • 2013-07-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多