我正在try 创建一个函数,当给定一个数据框和一个列时,该函数使用Rosner的测试(EnvStats::rosnerTest)来识别离群值,并返回一个新的数据框,这样我就可以判断每个离群值.

我可以在不使用函数的情况下实现这一点,但因为我有一个包含许多变量的数据框,所以我想创建一个函数来更快地实现这一点的自动化.(My previous post显示了一次执行一个变量的工作流程.)

以下是我的数据:

> dput(head(data))
structure(list(cap_date = structure(c(4856, 4860, 4860, 4861, 
4866, 4867), class = "Date"), cap_year = c(1983L, 1983L, 1983L, 
1983L, 1983L, 1983L), age_class = c("A", "S", "S", "A", "A", "A"), sex = 
c("F", "F", "F", "F", "F", "F"), alt = c(11, 12, 15.67000008, 7, 14.5, 
17.5), alb = c(2.599999905, 5.369999886, 4.670000076, 4.429999828, 3.75, 
3.700000048), alp = c(9, 86.33000183, 28, 170.6699982, 12, 82.5), 
tbil = c(0.200000003, 1.070000052, 0.430000007, 1.169999957, 
0.300000012, 0.400000006), bun = c(20, 17, 11.32999992, 56.33000183, 
7.5, 45), calcium = c(NA, 8.930000305, 8.800000191, 8.970000267, NA, 
7.550000191), crea = c(0.5, 0.569999993, 0.529999971, 0.600000024, 
1.049999952, 0.75), phos = c(2.75, 4.099999905, 4.96999979, 
5.329999924, 4.099999905, 7.400000095), pot = c(5.550000191, 
6.730000019, 3.869999886, 4.269999981, 3.049999952, 6.849999905), tp 
= c(4.449999809, 6.769999981, 5.800000191, 6.769999981, 5.75, 
6.400000095), sodium = c(NA, 142, 127, 138.3300018, 164, 139), glob = 
c(1.849999905, 1.400000095, 1.130000114, 2.340000153, 2, 
2.700000048), cortisol = c(4.24, 7.2231, 4.5431, NA, 6.0874, 4.8727), 
row = c(1L, 2L, 3L, 4L, 6L, 7L)), row.names = c(1L, 2L, 3L, 4L, 6L, 
7L), class = "data.frame")

以下是我的代码:

detect.outlier <- function(df, i, k) {  # i is a column/variable, and k is an input in the Rosner test

  plot(df$year, df[[i]], xlab = "Year", ylab = "Value") # I also want to print the plot

  ros.test <- rosnerTest(df[[i]], k)

  ros.results <- ros.test$all.stats

  ros.outliers <- ros.results %>% filter(Outlier) %>% select(Obs.Num) # filter by outlier = TRUE ; Obs.Num corresponds with row number in my data frame

  ros.outliers <- ros.outliers[,1]  # change from a data frame to a vector 

  outlier_df <- df[df$row %in% ros.outliers,]

  return(outlier_df %>% select(age_class, sex, i))

}

我try 运行该函数:

detect.outlier(data, alt, 20)

但我得到了一个错误:

Error during wrapup: recursive indexing failed at level 2

Error: no more error handlers available (recursive errors?); invoking 'abort' restart

我不确定这意味着什么,也不知道如何修复它--任何帮助都将不胜感激.非常感谢!

编辑:有时,当我运行该函数时,我也会收到这样的错误:

Error in rosnerTest(data$variable, k) : 'x' must be a numeric vector

这似乎很奇怪,因为当我进行类(data$alt)时,它会说它是数字.

编辑:Yama的解决方案是正确的. 我判断了代码以确保它返回了正确的异常值,而Rosner测试似乎返回了一个与行号不同的"Obs.Num".以下是使用函数中的解构代码的示例:

> ros.test <- rosnerTest(df$crea, k = 10)

Warning message:
In rosnerTest(df$crea, k = 10) :
3 observations with NA/NaN/Inf in 'x' removed.

> ros.results <- ros.test$all.stats

> print(ros.results)
   i   Mean.i      SD.i Value Obs.Num    R.i+1 lambda.i+1 Outlier
1  0 1.078450 0.3102488  3.35     222 7.321705   4.053146    TRUE
2  1 1.076295 0.3023919  2.55      12 4.873495   4.052913    TRUE
3  2 1.074895 0.2991009  2.35    1047 4.263125   4.052680    TRUE
4  3 1.073683 0.2966446  2.30     877 4.133960   4.052447    TRUE
5  4 1.072516 0.2943607  2.10     801 3.490560   4.052214   FALSE
6  5 1.071538 0.2927857  2.00     293 3.171133   4.051980   FALSE
7  6 1.070653 0.2915166  2.00     373 3.187974   4.051746   FALSE
8  7 1.069766 0.2902367  1.95     633 3.032814   4.051512   FALSE
9  8 1.068925 0.2890959  1.90     103 2.874737   4.051278   FALSE
10 9 1.068131 0.2880883  1.85     548 2.713992   4.051043   FALSE

> # 4 outliers flagged - obs. num 222, 12, 1047, and 877

> crea <- df[c(222, 12, 1047, 877),]

> crea %>% select(age_class, sex, crea, row)

     age_class sex crea  row
236          A   F 3.35  236
13           A   M 2.55   13
1154         A   M 2.35 1154
969          A   M 2.30  969

在这里,我们可以看到行号从222更改为236,从12更改为13,从1047更改为1154,从877更改为969

这最终会在我的函数行中产生影响

outlier_df <- df[df$row %in% ros.outliers,]

因为它随后会索引错误的行号.

任何帮助都是非常感谢的!

推荐答案

当您给出变量i时,您的函数会查找它.当您使用detect.outlier(data, alt, 20)调用函数时,i的值为alt.所以在你的函数detect.outlier()中,执行的代码是plot(df$year, df[[alt]], xlab = "Year", ylab = "Value"),而它应该是plot(df$year, df[["alt"]], xlab = "Year", ylab = "Value").

你可以通过写detect.outlier(df, "alt", 20)来纠正这一点.

显然,您的代码中还有另一个问题:

Error in xy.coords(x, y, xlabel, ylabel, log) :
'x' and 'y' lengths differ

但这应该已经对你有帮助了.

编辑:您应该提供rosnerTest函数的包名.

R相关问答推荐

如何根据条件计算时差(天)

如何使用R中的dhrr函数将李克特量表的因子列从长转换为宽?

使用gcuminc,如何使用逗号格式化风险表?

derrr mutate case_when grepl不能在R中正确返回值

如何动态更新selectizeInput?

我想在R中总结一个巨大的数据框架,使我只需要唯一的lat、lon、Date(Year)和Maxium Value""""""""

错误:非常长的R行中出现意外符号

通过在colname中查找其相应值来创建列

LOF中的插图短文字幕

用两种 colored颜色 填充方框图

从数据创建数字的命名列表.R中的框

R代码,用于在线条图下显示观测表

将统计检验添加到GGPUBR中的盒图,在R

错误包arrowR:READ_PARQUET/OPEN_DATASET&QOT;无法反序列化SARIFT:TProtocolException:超出大小限制&Quot;

有没有办法将基于每个值中出现的两个关键字或短语的字符串向量重新编码为具有这两个值的新向量?

如何显示准确的p值而不是<;0.001*?

使用同一行中的前一个值填充R矩阵中的缺失值

在REST API中使用参数R

将仪表板中的值框大小更改为Quarto

把代码写成dplyr中的group_by/摘要更简洁吗?