Loading the data from the MASS package

# Getting the data
cats <- MASS::cats

Examining the data:

Let’s start by looking at the data using slice_sample(data). Why slice_sample() instead of another function like head()? It’s not uncommon for the data sets available in R or online to have the data sorted in some way, so the first 6 rows might all be similar. In fact, the cats are sorted by sex, then Bwt, then Hwt.

# first six sorted rows
head(cats)
##   Sex Bwt Hwt
## 1   F 2.0 7.0
## 2   F 2.0 7.4
## 3   F 2.0 9.5
## 4   F 2.1 7.2
## 5   F 2.1 7.3
## 6   F 2.1 7.6
# six random rows
slice_sample(cats, n = 6)
##   Sex Bwt  Hwt
## 1   F 2.1  7.6
## 2   F 2.9 10.1
## 3   M 2.5 11.0
## 4   M 3.6 15.0
## 5   M 2.9 11.8
## 6   M 3.2 12.3

We can use summary(data) to summarize each column individually, including see the number of missing values by column (if any).

# Summary of each column
summary(cats)
##  Sex         Bwt             Hwt       
##  F:47   Min.   :2.000   Min.   : 6.30  
##  M:97   1st Qu.:2.300   1st Qu.: 8.95  
##         Median :2.700   Median :10.10  
##         Mean   :2.724   Mean   :10.63  
##         3rd Qu.:3.025   3rd Qu.:12.12  
##         Max.   :3.900   Max.   :20.50

There are 47 female cats (‘F’) and 97 male cats (‘M’). summary() also gives the mean and 5 number summary for each numeric (quantitative) column.

A better way is to visualize the data with either a histogram or density plot. I prefer density plots since there isn’t a need to specify the bin width or bin number, but either one works:

# Stacking both Bwt and Hwt into one column called cats_long
cats_long <- 
  cats |>
  dplyr::select(
    sex = Sex,
    `body weight (kg)` = Bwt,
    `heart weight (g)` = Hwt
  ) |>
  # adding an id column
  mutate(
    .before = 1,
    cat_id = row_number()
  ) |>
  pivot_longer(
    cols = c(-sex, -cat_id),
    names_to = 'feature',
    values_to = 'weight'
  )

# Creating the density plots
  ggplot(
    data = cats_long,
    mapping = aes(x = weight)
  ) +
  geom_density(
    fill = 'orange'
  ) + 
  facet_wrap(
    facets = vars(feature),
    nrow = 2,
    scales = 'free'
  ) + 
  labs(
    title = 'Body and heart weight of 144 cats',
    x = NULL
  ) + 
  theme_bw() +
  # Making the density plot 'sit' on the x-axis
  scale_y_continuous(
    expand = c(0, 0, 0.05, 0)
  )

Both heart and body weight of the cats are unimodal and right skewed. Body weight has a min of 2 kg, max of about 4 kg, and a mode of around 2.3 kgs

Heart weight has a min of about 6 g, max of about 10 g, and a mode of 10 g.

Summary stats

When using probability distributions, we often need to estimate the parameters. For numeric data, common probability distributions used have a mean parameter, \(\mu\), and a variance parameter, \(\sigma^2\), or standard deviation, \(\sigma\).

We estimate the parameters from the data using sample statistics:

\[\hat{\mu} = \bar{y} = \frac{1}{n}\sum_{i = 1}^n y_i\]

\[\hat{\sigma}^2 = s^2 = \frac{1}{n-1}\sum_{i = 1}^n (y_i-\bar{y})^2\]

\[\hat{\sigma} = s = \sqrt{\frac{1}{n-1}\sum_{i = 1}^n (y_i-\bar{y})^2}\]

To speed up the calculating the mean and standard deviation, we’ll use the cats_long data set created in the previous code chunk:

slice_sample(cats_long, n = 10)
## # A tibble: 10 × 4
##    cat_id sex   feature          weight
##     <int> <fct> <chr>             <dbl>
##  1    135 M     heart weight (g)   17.2
##  2     34 F     heart weight (g)   10.2
##  3      9 F     heart weight (g)    8.3
##  4     56 M     body weight (kg)    2.2
##  5     24 F     body weight (kg)    2.3
##  6     45 F     heart weight (g)   10.1
##  7     30 F     body weight (kg)    2.3
##  8    132 M     body weight (kg)    3.5
##  9     84 M     body weight (kg)    2.7
## 10    114 M     heart weight (g)   14.3

Now we’ll calculate the parameter estimates using the summarize() function in the dplyr package:

cats_long |>
  summarize(
    .by = feature,            # separate parameters for each RV
    avg = sum(weight) / n(),  # n() counts the number of rows used in the subset
    avg2 = mean(weight),      # or we can use the mean() function
    
    # Calculating the variability parameters
    variance = (sum((weight - mean(weight))^2)/(n() - 1)),
    variance2 = var(weight),
    stdev = sqrt(variance),
    stdev2 = sd(weight)
  )
## # A tibble: 2 × 7
##   feature            avg  avg2 variance variance2 stdev stdev2
##   <chr>            <dbl> <dbl>    <dbl>     <dbl> <dbl>  <dbl>
## 1 body weight (kg)  2.72  2.72    0.236     0.236 0.485  0.485
## 2 heart weight (g) 10.6  10.6     5.93      5.93  2.43   2.43
LS0tDQp0aXRsZTogJ1JhbmRvbSBWYXJpYWJsZXMgLSBDYXRzIGV4YW1wbGUnDQphdXRob3I6ICJDaGFwdGVyIDEiDQpkYXRlOiAiU1RBIDQyMTAiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgZmlnX3dpZHRoOiA2DQogICAgZmlnX2hlaWdodDogNg0KICAgIGZpZ19jYXB0aW9uOiB5ZXMNCiAgICBudW1iZXJfc2VjdGlvbnM6IG5vDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgY29kZV9kb3dubG9hZDogeWVzDQogICAgc21vb3RoX3Njcm9sbDogeWVzDQotLS0NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgZmlnLmFsaWduID0gJ2NlbnRlcicpDQpzZXQuc2VlZCg0MjEwKQ0KIyBMb2FkaW5nIHBhY2thZ2VzDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmBgYA0KDQpMb2FkaW5nIHRoZSBkYXRhIGZyb20gdGhlIGBNQVNTYCBwYWNrYWdlDQoNCmBgYHtyfQ0KIyBHZXR0aW5nIHRoZSBkYXRhDQpjYXRzIDwtIE1BU1M6OmNhdHMNCmBgYA0KDQojIyBFeGFtaW5pbmcgdGhlIGRhdGE6DQoNCkxldCdzIHN0YXJ0IGJ5IGxvb2tpbmcgYXQgdGhlIGRhdGEgdXNpbmcgYHNsaWNlX3NhbXBsZShkYXRhKWAuIFdoeSBgc2xpY2Vfc2FtcGxlKClgIGluc3RlYWQgb2YgYW5vdGhlciBmdW5jdGlvbiBsaWtlIGBoZWFkKClgPyBJdCdzIG5vdCB1bmNvbW1vbiBmb3IgdGhlIGRhdGEgc2V0cyBhdmFpbGFibGUgaW4gUiBvciBvbmxpbmUgdG8gaGF2ZSB0aGUgZGF0YSBzb3J0ZWQgaW4gc29tZSB3YXksIHNvIHRoZSBmaXJzdCA2IHJvd3MgbWlnaHQgYWxsIGJlIHNpbWlsYXIuIEluIGZhY3QsIHRoZSBjYXRzIGFyZSBzb3J0ZWQgYnkgYHNleGAsIHRoZW4gYEJ3dGAsIHRoZW4gYEh3dGAuDQoNCmBgYHtyfQ0KIyBmaXJzdCBzaXggc29ydGVkIHJvd3MNCmhlYWQoY2F0cykNCg0KIyBzaXggcmFuZG9tIHJvd3MNCnNsaWNlX3NhbXBsZShjYXRzLCBuID0gNikNCg0KYGBgDQoNCldlIGNhbiB1c2UgYHN1bW1hcnkoZGF0YSlgIHRvIHN1bW1hcml6ZSBlYWNoIGNvbHVtbiBpbmRpdmlkdWFsbHksIGluY2x1ZGluZyBzZWUgdGhlIG51bWJlciBvZiBtaXNzaW5nIHZhbHVlcyBieSBjb2x1bW4gKGlmIGFueSkuDQoNCmBgYHtyfQ0KIyBTdW1tYXJ5IG9mIGVhY2ggY29sdW1uDQpzdW1tYXJ5KGNhdHMpDQpgYGANCg0KVGhlcmUgYXJlIDQ3IGZlbWFsZSBjYXRzICgnRicpIGFuZCA5NyBtYWxlIGNhdHMgKCdNJykuIGBzdW1tYXJ5KClgIGFsc28gZ2l2ZXMgdGhlIG1lYW4gYW5kIDUgbnVtYmVyIHN1bW1hcnkgZm9yIGVhY2ggbnVtZXJpYyAocXVhbnRpdGF0aXZlKSBjb2x1bW4uDQoNCkEgYmV0dGVyIHdheSBpcyB0byB2aXN1YWxpemUgdGhlIGRhdGEgd2l0aCBlaXRoZXIgYSAqKmhpc3RvZ3JhbSoqIG9yICoqZGVuc2l0eSBwbG90KiouIEkgcHJlZmVyIGRlbnNpdHkgcGxvdHMgc2luY2UgdGhlcmUgaXNuJ3QgYSBuZWVkIHRvIHNwZWNpZnkgdGhlIGJpbiB3aWR0aCBvciBiaW4gbnVtYmVyLCBidXQgZWl0aGVyIG9uZSB3b3JrczoNCg0KYGBge3IgZGVuc2l0eV9wbG90fQ0KIyBTdGFja2luZyBib3RoIEJ3dCBhbmQgSHd0IGludG8gb25lIGNvbHVtbiBjYWxsZWQgY2F0c19sb25nDQpjYXRzX2xvbmcgPC0gDQogIGNhdHMgfD4NCiAgZHBseXI6OnNlbGVjdCgNCiAgICBzZXggPSBTZXgsDQogICAgYGJvZHkgd2VpZ2h0IChrZylgID0gQnd0LA0KICAgIGBoZWFydCB3ZWlnaHQgKGcpYCA9IEh3dA0KICApIHw+DQogICMgYWRkaW5nIGFuIGlkIGNvbHVtbg0KICBtdXRhdGUoDQogICAgLmJlZm9yZSA9IDEsDQogICAgY2F0X2lkID0gcm93X251bWJlcigpDQogICkgfD4NCiAgcGl2b3RfbG9uZ2VyKA0KICAgIGNvbHMgPSBjKC1zZXgsIC1jYXRfaWQpLA0KICAgIG5hbWVzX3RvID0gJ2ZlYXR1cmUnLA0KICAgIHZhbHVlc190byA9ICd3ZWlnaHQnDQogICkNCg0KIyBDcmVhdGluZyB0aGUgZGVuc2l0eSBwbG90cw0KICBnZ3Bsb3QoDQogICAgZGF0YSA9IGNhdHNfbG9uZywNCiAgICBtYXBwaW5nID0gYWVzKHggPSB3ZWlnaHQpDQogICkgKw0KICBnZW9tX2RlbnNpdHkoDQogICAgZmlsbCA9ICdvcmFuZ2UnDQogICkgKyANCiAgZmFjZXRfd3JhcCgNCiAgICBmYWNldHMgPSB2YXJzKGZlYXR1cmUpLA0KICAgIG5yb3cgPSAyLA0KICAgIHNjYWxlcyA9ICdmcmVlJw0KICApICsgDQogIGxhYnMoDQogICAgdGl0bGUgPSAnQm9keSBhbmQgaGVhcnQgd2VpZ2h0IG9mIDE0NCBjYXRzJywNCiAgICB4ID0gTlVMTA0KICApICsgDQogIHRoZW1lX2J3KCkgKw0KICAjIE1ha2luZyB0aGUgZGVuc2l0eSBwbG90ICdzaXQnIG9uIHRoZSB4LWF4aXMNCiAgc2NhbGVfeV9jb250aW51b3VzKA0KICAgIGV4cGFuZCA9IGMoMCwgMCwgMC4wNSwgMCkNCiAgKQ0KYGBgDQoNCkJvdGggaGVhcnQgYW5kIGJvZHkgd2VpZ2h0IG9mIHRoZSBjYXRzIGFyZSB1bmltb2RhbCBhbmQgcmlnaHQgc2tld2VkLiBCb2R5IHdlaWdodCBoYXMgYSBtaW4gb2YgMiBrZywgbWF4IG9mIGFib3V0IDQga2csIGFuZCBhIG1vZGUgb2YgYXJvdW5kIDIuMyBrZ3MNCg0KSGVhcnQgd2VpZ2h0IGhhcyBhIG1pbiBvZiBhYm91dCA2IGcsIG1heCBvZiBhYm91dCAxMCBnLCBhbmQgYSBtb2RlIG9mIDEwIGcuDQoNCiMjIyBTdW1tYXJ5IHN0YXRzDQoNCldoZW4gdXNpbmcgcHJvYmFiaWxpdHkgZGlzdHJpYnV0aW9ucywgd2Ugb2Z0ZW4gbmVlZCB0byBlc3RpbWF0ZSB0aGUgcGFyYW1ldGVycy4gRm9yIG51bWVyaWMgZGF0YSwgY29tbW9uIHByb2JhYmlsaXR5IGRpc3RyaWJ1dGlvbnMgdXNlZCBoYXZlIGEgbWVhbiBwYXJhbWV0ZXIsICRcbXUkLCBhbmQgYSB2YXJpYW5jZSBwYXJhbWV0ZXIsICRcc2lnbWFeMiQsIG9yIHN0YW5kYXJkIGRldmlhdGlvbiwgJFxzaWdtYSQuDQoNCldlIGVzdGltYXRlIHRoZSBwYXJhbWV0ZXJzIGZyb20gdGhlIGRhdGEgdXNpbmcgc2FtcGxlIHN0YXRpc3RpY3M6DQoNCiQkXGhhdHtcbXV9ID0gXGJhcnt5fSA9IFxmcmFjezF9e259XHN1bV97aSA9IDF9Xm4geV9pJCQNCg0KJCRcaGF0e1xzaWdtYX1eMiA9IHNeMiA9IFxmcmFjezF9e24tMX1cc3VtX3tpID0gMX1ebiAoeV9pLVxiYXJ7eX0pXjIkJA0KDQokJFxoYXR7XHNpZ21hfSA9IHMgPSBcc3FydHtcZnJhY3sxfXtuLTF9XHN1bV97aSA9IDF9Xm4gKHlfaS1cYmFye3l9KV4yfSQkDQoNClRvIHNwZWVkIHVwIHRoZSBjYWxjdWxhdGluZyB0aGUgbWVhbiBhbmQgc3RhbmRhcmQgZGV2aWF0aW9uLCB3ZSdsbCB1c2UgdGhlIGBjYXRzX2xvbmdgIGRhdGEgc2V0IGNyZWF0ZWQgaW4gdGhlIHByZXZpb3VzIGNvZGUgY2h1bms6DQoNCmBgYHtyfQ0Kc2xpY2Vfc2FtcGxlKGNhdHNfbG9uZywgbiA9IDEwKQ0KYGBgDQoNCk5vdyB3ZSdsbCBjYWxjdWxhdGUgdGhlIHBhcmFtZXRlciBlc3RpbWF0ZXMgdXNpbmcgdGhlIGBzdW1tYXJpemUoKWAgZnVuY3Rpb24gaW4gdGhlIGBkcGx5cmAgcGFja2FnZToNCg0KYGBge3J9DQpjYXRzX2xvbmcgfD4NCiAgc3VtbWFyaXplKA0KICAgIC5ieSA9IGZlYXR1cmUsICAgICAgICAgICAgIyBzZXBhcmF0ZSBwYXJhbWV0ZXJzIGZvciBlYWNoIFJWDQogICAgYXZnID0gc3VtKHdlaWdodCkgLyBuKCksICAjIG4oKSBjb3VudHMgdGhlIG51bWJlciBvZiByb3dzIHVzZWQgaW4gdGhlIHN1YnNldA0KICAgIGF2ZzIgPSBtZWFuKHdlaWdodCksICAgICAgIyBvciB3ZSBjYW4gdXNlIHRoZSBtZWFuKCkgZnVuY3Rpb24NCiAgICANCiAgICAjIENhbGN1bGF0aW5nIHRoZSB2YXJpYWJpbGl0eSBwYXJhbWV0ZXJzDQogICAgdmFyaWFuY2UgPSAoc3VtKCh3ZWlnaHQgLSBtZWFuKHdlaWdodCkpXjIpLyhuKCkgLSAxKSksDQogICAgdmFyaWFuY2UyID0gdmFyKHdlaWdodCksDQogICAgc3RkZXYgPSBzcXJ0KHZhcmlhbmNlKSwNCiAgICBzdGRldjIgPSBzZCh3ZWlnaHQpDQogICkNCmBgYA0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQo=