【问题标题】:R: Error in UseMethod("group_by_") : applied to an object of classR:UseMethod(“group_by_”)中的错误:应用于类的对象
【发布时间】:2018-06-25 16:24:06
【问题描述】:

我正在处理我应该读取 csv 文件的作业,然后将其发送到要转换为类对象的函数。我设法读取了 csv 文件并将其转换为对象:

make_LD <- function(x){
  structure(list(id = c(x$id), visit = c(x$visit),
                 room = c(x$room), value = c(x$value), timepoint = c(x$timepoint)), class = "LongitudinalData")
}

输入 CSV 文件的可重现版本是:

data <- structure(list(id = c(14L, 14L, 14L, 14L, 14L, 14L, 14L, 14L, 
14L, 14L, 14L, 14L, 14L, 14L, 14L, 14L, 14L, 14L, 14L, 14L), 
    visit = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
    0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L), room = c("bedroom", "bedroom", 
    "bedroom", "bedroom", "bedroom", "bedroom", "bedroom", "bedroom", 
    "bedroom", "bedroom", "bedroom", "bedroom", "bedroom", "bedroom", 
    "bedroom", "bedroom", "bedroom", "bedroom", "bedroom", "bedroom"
    ), value = c(6, 6, 2.75, 2.75, 2.75, 2.75, 6, 6, 2.75, 2.75, 
    2.75, 2.75, 2.75, 2.75, 2.75, 2.75, 2.75, 2.75, 2.75, 2.75
    ), timepoint = 53:72), .Names = c("id", "visit", "room", 
"value", "timepoint"), class = "data.frame", row.names = c(NA, 
-20L))

我是如何运行这段代码的:

## Read in the data
library(readr)
library(magrittr)
library(dplyr)
source("oop_code_2.R")
## Load any other packages that you may need to execute your code

data <- read_csv("data/MIE.csv")
x <- make_LD(data)
out <- subject(x, 14)

完成此操作后,我使用对象变量并将其发送到通用函数:

subject <- function(x, id) UseMethod("subject")
subject.LongitudinalData <- function(x, subj){
  subj_exist <- x %>%
    group_by_(x$id) %>%
    filter(x$id == subj)
  return(subj_exist)
}

当我运行代码时,它会产生错误:

Error in UseMethod("group_by_") : 
  no applicable method for 'group_by_' applied to an object of class "LongitudinalData"

我注意到读入的 csv 文件的格式是按列组织的,而我将其发送为对象后的数据格式已更改为字段。

问题是,我做错了什么? 谢谢!

编辑/添加:

当我对来自 csv 的数据运行此代码时,它可以正常工作,如下所示。如果这有帮助。

> datatest1 <- data %>%
+ group_by(id, visit, room) %>%
+ select(id, visit, room , value) %>%
+ filter(id == 14) %>%
+ summarise(valmean = mean(value))
> print(datatest1)
# A tibble: 6 x 4
# Groups:   id, visit [?]
     id visit         room   valmean
  <int> <int>        <chr>     <dbl>
1    14     0      bedroom  4.786592
2    14     0  living room  2.750000
3    14     1      bedroom  3.401442
4    14     1 family  room  8.426549
5    14     2      bedroom 18.583635
6    14     2  living room 22.550694

在 LongitudinalData 对象上完成后,会引发错误:

> datatest2 <- x %>%
+ group_by(id, visit, room) %>%
+ select(id, visit, room , value) %>%
+ filter(id == 14) %>%
+ summarise(valmean = mean(values))
Error in UseMethod("group_by_") : 
  no applicable method for 'group_by_' applied to an object of class "LongitudinalData"

这也可能来自数据的格式化方式。下面是数据在转换为 LongitudinalData 对象之前和之后的样子的示例。

> head(data)
# A tibble: 6 x 5
     id visit    room value timepoint
  <int> <int>   <chr> <dbl>     <int>
1    14     0 bedroom  6.00        53
2    14     0 bedroom  6.00        54
3    14     0 bedroom  2.75        55
4    14     0 bedroom  2.75        56
5    14     0 bedroom  2.75        57
6    14     0 bedroom  2.75        58
> head(x)
$id
   [1] 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14
  [40] 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14
  [79] 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14
$visit
   [1] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
  [60] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 [119] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

这是数据的链接:data

【问题讨论】:

  • 你到底想用group_by_(x$id)做什么?目前尚不清楚您要做什么,因此不清楚您做错了什么。您可能不想要该函数的下划线版本,并且您可能希望省略 x$ 部分。
  • 我的目标是将所有具有相同 id 的条目分组,并最终获得它们的值的平均值。
  • 如果您提供带有示例输入和所需输出的reproducible example,会更容易提供帮助。
  • 添加了一个例子,如果有帮助的话。
  • 请添加一个可重现的示例,您可以在其中创建数据框或提供指向我们可以自己下载的文件的链接,@afterafx

标签: r csv dplyr


【解决方案1】:

我也在做同样的任务,我正在使用 S4 课程。

这是我的解决方案:

library(dplyr)

setClass('longitudinalData', 
         representation = representation(
                        id = "numeric", 
                        visit = "numeric",
                        room = "character",
                        value = "numeric",
                        timepoint = 'numeric')
         )


data = data.frame( id = rbinom(1000, 10, .75),
                   visit = sample(1:3, 1000, replace = TRUE),
                   room = sample(letters[1:5], 1000, replace = TRUE),
                   value = rnorm(1000, 50, 10),
                   timepoint = abs(rnorm(1000))
)

make_LD = function(data){
  new("longitudinalData", 
      id = as.numeric(data$id),
      visit = as.numeric(data$visit), 
      room = as.character(data$room),
      value = as.numeric(data$value),
      timepoint =as.numeric(data$timepoint))
}

x = make_LD (data)
print(x)

setGeneric(name = 'subject', def = function(.Object, n=1){standardGeneric('subject')})

setMethod(f='subject', signature = 'longitudinalData',
          definition = function(.Object, n=1) {
            if(n %in% .Object@id){
            x = data.frame(as.factor(.Object@id), as.factor(.Object@visit), .Object@room, .Object@value, .Object@timepoint)
            names(x) = c( 'id', 'visit', 'room', 'value', 'timepoint')
            out = x[which(x$id == n),] %>% group_by(visit)
            return(out)
            } else { stop(paste("Subject", n, "is not available", sep = " "))}
          })


subject(x, n=4) %>% summary

请注意,我在 setMethod 中使用了 data.frame,以便可以在其上使用已知(有效)dplyr 函数。

输出如下:

> subject(x, n=4) %>% summary
       id     visit room      value         timepoint      
 4      :12   1:2   a:2   Min.   :25.04   Min.   :0.02548  
 2      : 0   2:4   b:2   1st Qu.:44.80   1st Qu.:0.20043  
 3      : 0   3:6   c:1   Median :50.42   Median :0.53025  
 5      : 0         d:3   Mean   :47.73   Mean   :0.71829  
 6      : 0         e:4   3rd Qu.:52.44   3rd Qu.:1.13632  
 7      : 0               Max.   :64.83   Max.   :1.88971  
 (Other): 0 

id 字段的输出看起来不太好。我认为这很容易解决。

请随意编辑这方面的答案。

希望对你有帮助!!

【讨论】:

    【解决方案2】:

    在将class 属性设置为"LongitudinalData" 时,您是在告诉R 只使用.LongitudinalData 的方法。就像您如何定义一个在执行 subject(x, 14) 时调用的 subject.LongitudinalData 一样,当您调用 group_by_ 时,R 会查找 group_by_.LongitudinalData,但这当然不存在,因为您刚刚发明了班级。

    不过,R 有一个简单的类似继承的特性,因此您可以指定备份类以在主类没有方法的情况下进行尝试。

    来自?class

    当泛型函数 fun 应用于具有类属性 c("first", "second") 的对象时,系统会搜索名为 fun.first 的函数,如果找到,则将其应用于对象。如果没有找到这样的函数,就会尝试一个名为 fun.second 的函数。如果没有类名产生合适的函数,则使用函数 fun.default(如果存在)。如果没有class属性,则尝试隐式类,然后默认方法。

    因此,您可以指定您的 LongitudinalData 对象也可以像这样的数据框处理:

    make_LD <- function(x){
      structure(list(id = c(x$id), visit = c(x$visit),
                     room = c(x$room), value = c(x$value), timepoint = c(x$timepoint)), 
      class = c("LongitudinalData", "data.frame"))
    }
    

    但是,数据框缺少一些额外的结构,因此通常最好通过构建现有对象来创建新类,而不是从头开始创建一个:

    make_LD <- function (x) {
      class(x) <- c("LongitudinalData", class(x))
      x
    }
    

    请注意,您的 subject.LongitudinalData 方法还存在一些其他问题,需要先纠正它才能起作用。我建议阅读vignette("programming", package = "dplyr")

    【讨论】:

    • 如果我将函数更改为也被视为数据框,当我打印出class(x) 时,它会同时显示 LongitudinalData 和数据框。我的任务要求它只说明 LongitudinalData。这还有可能吗?
    • 那么你有两个选择:定义新方法group_by_.LongitudinalDataet cetera 来教每个 dplyr 方法如何使用你的类,或者使用基函数而不是 dplyr。很遗憾你的班级正在教坏习惯。
    • 看来这些是我唯一的选择。您的回答可以消除错误。
    【解决方案3】:

    我阅读了您在评论中添加的 csv 文件作为您以这种方式使用的来源:

    #replace you path for csv file as it is in your computer
    df <- read.csv("C:/Users/username/Desktop/_257dbf6be13177cd110e3ef91b34ff67_data/data/MIE.csv", header=TRUE, sep=",", stringsAsFactors=FALSE)
    

    我运行你的代码:

    make_LD <- function(x){
      structure(list(id = c(x$id), visit = c(x$visit),
                     room = c(x$room), value = c(x$value), timepoint = c(x$timepoint)), class = "LongitudinalData")
    }
    
    subject <- function(x, id) UseMethod("subject")
    subject.LongitudinalData <- function(x, subj){
      subj_exist <- x %>%
        group_by_(x$id) %>%
        filter(x$id == subj)
      return(subj_exist)
    }
    

    我没有收到任何错误。

    【讨论】:

    • 直接使用数据时有效,但数据转换为 LongitudinalData 对象时无效。我包含了上面的代码,显示了我如何使用数据。
    • @afterafx 你用哪个包来做这个?
    • 使用library(dplyr)
    • @afterafx 好的。在 x 来自哪里的 datatest2 的代码中?它是您从 csv 读取过程中获得的数据框吗?因为从第一个代码块开始,它是不可用的 x
    • 如果你看第三块代码,x 是从:x &lt;- make_LD(data) 生成的。 data 是从 csv 文件中读取的内容。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-12
    • 2022-12-15
    • 2020-12-05
    • 2020-04-10
    • 2023-04-06
    • 2018-03-03
    相关资源
    最近更新 更多