Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert fitdistrplus::fitdist summary into tidy format?

Tags:

r

tidyverse

broom

I have the following code:

x <- c(
  0.367141764080875, 0.250037975705769, 0.167204185003365, 0.299794433447383,
  0.366885973041269, 0.300453205296379, 0.333686861081341, 0.33301168850398,
  0.400142004893329, 0.399433677388411, 0.366077304765104, 0.166402979455671,
  0.466624230750293, 0.433499934139897, 0.300017278751768, 0.333673696762895,
  0.29973685692478
)

fn <- fitdistrplus::fitdist(x,"norm")
summary(fn)
#> Fitting of the distribution ' norm ' by maximum likelihood 
#> Parameters : 
#>        estimate Std. Error
#> mean 0.32846024 0.01918923
#> sd   0.07911922 0.01355908
#> Loglikelihood:  19.00364   AIC:  -34.00727   BIC:  -32.34084 
#> Correlation matrix:
#>      mean sd
#> mean    1  0
#> sd      0  1

Basically, it takes a vector and tried to fit the distribution using fitdistrplus package.

I tried looking at the broom package, but it doesn't have a function that covers that.

like image 660
scamander Avatar asked Jul 20 '18 02:07

scamander


People also ask

What does Fitdist do in R?

The fitdist function returns an S3 object of class "fitdist" for which print, summary and plot functions are provided. The fit of a distribution using fitdist assumes that the corresponding d, p, q functions (stand- ing respectively for the density, the distribution and the quantile functions) are defined.

What package is Fitdist?

Description Extends the fitdistr() function (of the MASS package) with several functions to help the fit of a parametric distribution to non-censored or censored data. Censored data may contain left censored, right censored and interval censored values, with several lower and upper bounds.


1 Answers

When you call broom::tidy(fn) you receive an error that says:

Error: No tidy method for objects of class fitdist

This is because this function from broom only has a finite number objects that are "good to use", see methods(tidy) for the complete list. (Read more about S3 methods in R. More here).

So the function doesn't work for an object fitdist but works for a fitdistr object from MASS (more "famous").

We can then assign to fn that class, and then use broom:

class(fn) <- ("fitdist", "fitdistr") 
# notice that I've kept the original class and added the other
# you shouldn't overwrite classes. ie: don't to this: class(fn) <- "fitdistr"

broom::tidy(fn)
# # A tibble: 2 x 3
# term  estimate std.error
# <chr>    <dbl>     <dbl>
# 1 mean    0.328     0.0192
# 2 sd      0.0791    0.0136

Note that you can only see the parameters. If you wish to see more and organize everything as "tidy", you should tell us more about your expected output.

broom::tidy() gets you this far, if you want more I'd start by defining my own method function that works for a class fitdist object using as reference the tidy.fitdistr method, and adapting it.


Example of how I'd adapt from the original broom::tidy() code, using the S3 method for the class fitdist.

Define your own method (similar to how you define your own function):

# necessary libraries
library(dplyr)
library(broom)

# method definition:
tidy.fitdist <- function(x, ...) { # notice the use of .fitdist

  # you decide what you want to keep from summary(fn)
  # use fn$ecc... to see what you can harvest

  e1 <- tibble(
    term = names(x$estimate),
    estimate = unname(x$estimate),
    std.error = unname(x$sd)
  )

  e2 <- tibble(
    term = c("loglik", "aic", "bic"),
    value = c(unname(x$loglik), unname(x$aic), unname(x$bic))
  )

  e3 <- x$cor # I prefer this to: as_tibble(x$cor)

  list(e1, e2, e3) # you can name each element for a nicer result
  # example: list(params = e1, scores = e2, corrMatr = e3)
}

This is how you can call this new method now:

tidy(fn) # to be more clear this is calling your tidy.fitdist(fn) under the hood.
# [[1]]
# # A tibble: 2 x 3
# term  estimate std.error
# <chr>    <dbl>     <dbl>
# 1 mean    0.328     0.0192
# 2 sd      0.0791    0.0136
# 
# [[2]]
# # A tibble: 3 x 2
# term   value
# <chr>  <dbl>
# 1 loglik  19.0
# 2 aic    -34.0
# 3 bic    -32.3
# 
# [[3]]
#      mean sd
# mean    1  0
# sd      0  1

Notice that the class is:

class(fn)
[1] "fitdist"

So now you don't actually need to assign the fitdistr (from MASS) class as before.

like image 171
RLave Avatar answered Nov 01 '22 07:11

RLave