Source of the codes and discussions:
Check your outliers! An introduction to identifying statistical outliers in R with easystats

Univariate

library(performance)

# Create some artificial outliers and an ID column
data <- rbind(mtcars[1:4], 12, 55)
data <- cbind(car = row.names(data), data)

Check outliers using zscore robust method:

outliers <- check_outliers(data, method = "zscore_robust", ID = "car")
outliers
1 outlier detected: case 34.
- Based on the following method and threshold: zscore_robust (3.291).
- For variables: mpg, cyl, disp, hp.

-----------------------------------------------------------------------------
 
The following observations were considered outliers for two or more
  variables by at least one of the selected methods:

  Row car n_Zscore_robust
1  34  34               2

-----------------------------------------------------------------------------
Outliers per variable (zscore_robust): 

$mpg
   Row car Distance_Zscore_robust
34  34  34               6.271888

$cyl
   Row car Distance_Zscore_robust
34  34  34               16.52502
which(outliers)        # get row index of outlier
[1] 34
data_clean <- data[-which(outliers), ]   # remove outlier from data

Plot outliers:

library(see)

plot(outliers) +
  ggplot2::theme(axis.text.x = ggplot2::element_text(
    angle = 45, size = 8
  ))

Multivariate Outliers

Using a robust version of the Mahalanobis distance method - the minimum covariance determinant method:

outliers <- check_outliers(data, method = "mcd")
outliers
2 outliers detected: cases 33, 34.
- Based on the following method and threshold: mcd (20).
- For variables: mpg, cyl, disp, hp.
plot(outliers) +
  ggplot2::theme(axis.text.x = ggplot2::element_text(
    angle = 45, size = 8
  ))

Model Based Outliers

model <- lm(mpg ~ disp * hp, data = data)
outliers <- check_outliers(model, method = "cook")
outliers
1 outlier detected: case 33.
- Based on the following method and threshold: cook (0.806).
- For variable: (Whole model).
plot(outliers)

Composite Outlier Score

outliers <- check_outliers(model, method = c("zscore_robust", "mcd", "cook"))
outliers
2 outliers detected: cases 33, 34.
- Based on the following methods and thresholds: zscore_robust (3.291),
  mcd (0.806), cook (20).
- For variable: (Whole model).

Note: Outliers were classified as such by at least half of the selected methods. 

-----------------------------------------------------------------------------
 
The following observations were considered outliers for two or more
  variables by at least one of the selected methods:

  Row n_Zscore_robust          n_MCD         n_Cook
1  34               1 (Multivariate)              0
2  31               0 (Multivariate)              0
3  33               0 (Multivariate) (Multivariate)
which(outliers)
[1] 33 34
attributes(outliers)$outlier_var$zscore_robust
$mpg
   Row Distance_Zscore_robust
34  34               6.271888

Handling Outliers

Winsorization

Removing outliers that do not belong to the distribution of interest can in this case be a valid strategy, and ideally one would report results with and without outliers to see the extent of their impact on results. This approach, however, can reduce statistical power. Therefore, some propose a recoding approach, namely, winsorization: bringing outliers back within acceptable limits (e.g., three MADs, Tukey & McLaughlin, 1963). However, if possible, it is recommended to collect enough data so that even after removing outliers, there is still sufcient statistical power without having to resort to winsorization (Leys et al., 2019).

data[33:34, 2:3]  # See outliers rows
   mpg cyl
33  12  12
34  55  55
# Winsorizing using the MAD
library(datawizard)
winsorized_data <- winsorize(data, method = "zscore", robust = TRUE, threshold = 3)
# Outlier values > +/- MAD have been winsorized
winsorized_data[33:34, 2:3]
        mpg     cyl
33 12.00000 12.0000
34 36.32403 14.8956
LS0tDQp0aXRsZTogIk91dGxpZXIgRGV0ZWN0aW9uIg0KYXV0aG9yOiAnTUQgQUhTQU5VTCBJU0xBTScNCm91dHB1dDogDQogIGh0bWxfZG9jdW1lbnQ6DQogICAgIyB0aGVtZTogZmxhdGx5DQogICAgdG9jOiB0cnVlDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgdG9jX2RlcHRoOiA0DQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KLS0tDQoNCmBgYHtyLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KA0KICBjb21tZW50ID0gIiIsIHByb21wdCA9IEYsIG1lc3NhZ2U9Riwgd2FybmluZyA9IEYNCikNCmBgYA0KDQotLS0NCg0KU291cmNlIG9mIHRoZSBjb2RlcyBhbmQgZGlzY3Vzc2lvbnM6ICAgDQpbQ2hlY2sgeW91ciBvdXRsaWVycyEgQW4gaW50cm9kdWN0aW9uIHRvIGlkZW50aWZ5aW5nIHN0YXRpc3RpY2FsIG91dGxpZXJzIGluIFIgd2l0aCBlYXN5c3RhdHNdKGh0dHBzOi8vbGluay5zcHJpbmdlci5jb20vYXJ0aWNsZS8xMC4zNzU4L3MxMzQyOC0wMjQtMDIzNTYtdykNCg0KIyMgVW5pdmFyaWF0ZQ0KDQpgYGB7cn0NCmxpYnJhcnkocGVyZm9ybWFuY2UpDQoNCiMgQ3JlYXRlIHNvbWUgYXJ0aWZpY2lhbCBvdXRsaWVycyBhbmQgYW4gSUQgY29sdW1uDQpkYXRhIDwtIHJiaW5kKG10Y2Fyc1sxOjRdLCAxMiwgNTUpDQpkYXRhIDwtIGNiaW5kKGNhciA9IHJvdy5uYW1lcyhkYXRhKSwgZGF0YSkNCmBgYA0KDQpDaGVjayBvdXRsaWVycyB1c2luZyB6c2NvcmUgcm9idXN0IG1ldGhvZDoNCmBgYHtyfQ0Kb3V0bGllcnMgPC0gY2hlY2tfb3V0bGllcnMoZGF0YSwgbWV0aG9kID0gInpzY29yZV9yb2J1c3QiLCBJRCA9ICJjYXIiKQ0Kb3V0bGllcnMNCmBgYA0KDQpgYGB7cn0NCndoaWNoKG91dGxpZXJzKSAgICAgICAgIyBnZXQgcm93IGluZGV4IG9mIG91dGxpZXINCmRhdGFfY2xlYW4gPC0gZGF0YVstd2hpY2gob3V0bGllcnMpLCBdICAgIyByZW1vdmUgb3V0bGllciBmcm9tIGRhdGENCmBgYA0KDQpQbG90IG91dGxpZXJzOg0KDQpgYGB7cn0NCmxpYnJhcnkoc2VlKQ0KDQpwbG90KG91dGxpZXJzKSArDQogIGdncGxvdDI6OnRoZW1lKGF4aXMudGV4dC54ID0gZ2dwbG90Mjo6ZWxlbWVudF90ZXh0KA0KICAgIGFuZ2xlID0gNDUsIHNpemUgPSA4DQogICkpDQpgYGANCg0KIyBNdWx0aXZhcmlhdGUgT3V0bGllcnMNCg0KVXNpbmcgYSByb2J1c3QgdmVyc2lvbiBvZiB0aGUgTWFoYWxhbm9iaXMgZGlzdGFuY2UgbWV0aG9kIC0gdGhlIG1pbmltdW0gY292YXJpYW5jZSBkZXRlcm1pbmFudCBtZXRob2Q6DQpgYGB7cn0NCm91dGxpZXJzIDwtIGNoZWNrX291dGxpZXJzKGRhdGEsIG1ldGhvZCA9ICJtY2QiKQ0Kb3V0bGllcnMNCmBgYA0KDQoNCmBgYHtyfQ0KcGxvdChvdXRsaWVycykgKw0KICBnZ3Bsb3QyOjp0aGVtZShheGlzLnRleHQueCA9IGdncGxvdDI6OmVsZW1lbnRfdGV4dCgNCiAgICBhbmdsZSA9IDQ1LCBzaXplID0gOA0KICApKQ0KYGBgDQoNCiMgTW9kZWwgQmFzZWQgT3V0bGllcnMNCg0KYGBge3J9DQptb2RlbCA8LSBsbShtcGcgfiBkaXNwICogaHAsIGRhdGEgPSBkYXRhKQ0Kb3V0bGllcnMgPC0gY2hlY2tfb3V0bGllcnMobW9kZWwsIG1ldGhvZCA9ICJjb29rIikNCm91dGxpZXJzDQpgYGANCg0KYGBge3J9DQpwbG90KG91dGxpZXJzKQ0KYGBgDQoNCiMjIENvbXBvc2l0ZSBPdXRsaWVyIFNjb3JlDQoNCmBgYHtyfQ0Kb3V0bGllcnMgPC0gY2hlY2tfb3V0bGllcnMobW9kZWwsIG1ldGhvZCA9IGMoInpzY29yZV9yb2J1c3QiLCAibWNkIiwgImNvb2siKSkNCm91dGxpZXJzDQp3aGljaChvdXRsaWVycykNCmF0dHJpYnV0ZXMob3V0bGllcnMpJG91dGxpZXJfdmFyJHpzY29yZV9yb2J1c3QNCmBgYA0KDQojIEhhbmRsaW5nIE91dGxpZXJzDQoNCiMjIFdpbnNvcml6YXRpb24NCg0KUmVtb3Zpbmcgb3V0bGllcnMgdGhhdCBkbyBub3QgYmVsb25nIHRvIHRoZSBkaXN0cmlidXRpb24gb2YgaW50ZXJlc3QgY2FuIGluIHRoaXMgY2FzZSBiZSBhIHZhbGlkIHN0cmF0ZWd5LCBhbmQgaWRlYWxseSBvbmUgd291bGQgcmVwb3J0IHJlc3VsdHMgd2l0aCBhbmQgd2l0aG91dCBvdXRsaWVycyB0byBzZWUgdGhlDQpleHRlbnQgb2YgdGhlaXIgaW1wYWN0IG9uIHJlc3VsdHMuIFRoaXMgYXBwcm9hY2gsIGhvd2V2ZXIsIGNhbiByZWR1Y2Ugc3RhdGlzdGljYWwgcG93ZXIuIFRoZXJlZm9yZSwgc29tZSBwcm9wb3NlIGEgcmVjb2RpbmcgYXBwcm9hY2gsIG5hbWVseSwgd2luc29yaXphdGlvbjogYnJpbmdpbmcgb3V0bGllcnMNCmJhY2sgd2l0aGluIGFjY2VwdGFibGUgbGltaXRzIChlLmcuLCB0aHJlZSBNQURzLCBUdWtleSAmIE1jTGF1Z2hsaW4sIDE5NjMpLiBIb3dldmVyLCBpZiBwb3NzaWJsZSwgaXQgaXMgcmVjb21tZW5kZWQgdG8gY29sbGVjdCBlbm91Z2ggZGF0YSBzbyB0aGF0IGV2ZW4gYWZ0ZXIgcmVtb3Zpbmcgb3V0bGllcnMsDQp0aGVyZSBpcyBzdGlsbCBzdWZjaWVudCBzdGF0aXN0aWNhbCBwb3dlciB3aXRob3V0IGhhdmluZyB0byByZXNvcnQgdG8gd2luc29yaXphdGlvbiAoTGV5cyBldCBhbC4sIDIwMTkpLg0KDQpgYGB7cn0NCmRhdGFbMzM6MzQsIDI6M10gICMgU2VlIG91dGxpZXJzIHJvd3MNCmBgYA0KDQpgYGB7cn0NCiMgV2luc29yaXppbmcgdXNpbmcgdGhlIE1BRA0KbGlicmFyeShkYXRhd2l6YXJkKQ0Kd2luc29yaXplZF9kYXRhIDwtIHdpbnNvcml6ZShkYXRhLCBtZXRob2QgPSAienNjb3JlIiwgcm9idXN0ID0gVFJVRSwgdGhyZXNob2xkID0gMykNCmBgYA0KDQpgYGB7cn0NCiMgT3V0bGllciB2YWx1ZXMgPiArLy0gTUFEIGhhdmUgYmVlbiB3aW5zb3JpemVkDQp3aW5zb3JpemVkX2RhdGFbMzM6MzQsIDI6M10NCmBgYA0K