按因子级别和列识别 R 数据中的异常值
Identifying outliers in R data by factor levels and columns
我有一个定期更新的生物数据库,目前包含 250 个物种的 13,500 个人的记录(物种 = 第一列中的因子水平)。每个人都有一个唯一的 ID(第 2 列)。对于每个人,记录了 7 个不同的测量值(第 3-9 列)。将这么多值手动输入数据库后,我确定会出现一些拼写错误并产生异常值,例如,应该读取 15.2 的测量值可能输入为 1.52 或 152 或 25.2。我想找出那些异常值,这样我就可以修复它们而不是将它们丢弃,但是有太多的物种无法根据具体情况进行处理。我如何自动化和组织对每个物种的每个测量子集的离群值搜索的输出?最后一部分很关键,因为每个物种的大小可能不同,测量值也大不相同。我正在尝试尽可能地简化,因为每次将新一批数据添加到数据库时(或者直到有人申请 filemaker 许可证),这可能会完成。
我在 R 中进行分析。我认为对于所有超出均值 2 或 3 个标准差的值的嵌套 for 循环就可以解决问题,and/or group_by 使用 dplyr 和分位数功能。但是我一直无法弄清楚如何在返回实际异常值的同时 运行 所有列。还有许多其他问题可以解决其中的一些问题,但我找不到将所有问题放在一起的问题。
示例数据:
df = data.frame(
species = c("a","b","a","b","a","b","a","b","a","b"),
uniqueID = c("x01","x02","x03","x04","x05","x06","x07","x08","x09","x10"),
metric1 = c(1,2,3,1,2,3,1,2,3,11),
metric2 = c(4,5,6,4,5,6,55,4,5,6),
metric3 = c(0.7,7,8,9,7,8,9,77,8,9)
)
就预期结果而言,我正在设想一个 data.frame 或矩阵报告物种,unique_ID,measurement/column 具有离群值,以及离群值本身。但是如何格式化并不重要,例如:
outliers = data.frame(
species = c("a","a","b","b"),
uniqueID = c("x01","x07","x08","x10"),
var = c("metric3","metric2","metric3","metric1"),
value = c(0.7,55,77,11)
)
提前致谢!
从您提供的数据开始...
df = data.frame(
species = c("a","b","a","b","a","b","a","b","a","b"),
uniqueID = c("x01","x02","x03","x04","x05","x06","x07","x08","x09","x10"),
metric1 = c(1,2,3,1,2,3,1,2,3,11),
metric2 = c(4,5,6,4,5,6,55,4,5,6),
metric3 = c(0.7,7,8,9,7,8,9,77,8,9)
)
我将在这里大量使用 tidyverse
...
library(tidyverse)
然后将行数增加三倍,这样标准偏差计算就不会死在我们身上,并添加另一个离群值行...
df2 <- df %>%
bind_rows(df) %>%
bind_rows(df) %>%
add_row(
species = "a",
uniqueID = "x01",
metric1 = 1,
metric2 = 4,
metric3 = 1e12
)
如果你尝试这样的事情会怎样?
df2 %>%
gather(key = "metric", value = "value", -species, -uniqueID) %>%
group_by(species, uniqueID, metric) %>%
arrange(species, uniqueID, metric) %>% # just to make the results easy to scan
mutate(
mean_obs = mapply(function(x) mean(value[-x]), 1:n()),
stdev = mapply(function(x) sd(value[-x]), 1:n()),
minimum = mean_obs - stdev * 2,
maximum = mean_obs + stdev * 2,
outlier = value < minimum | value > maximum
) %>%
filter(outlier) %>%
glimpse()
借鉴求均值和标准差不包括当前记录,然后如果某行大于2则标记为离群值平均值的 SD。
如果您排除当前记录并且该记录不是异常值,它会变得很奇怪,它会明显改变平均值和标准偏差。但是如果记录 是 一个离群值,你肯定想这样做。 :)
我有一个定期更新的生物数据库,目前包含 250 个物种的 13,500 个人的记录(物种 = 第一列中的因子水平)。每个人都有一个唯一的 ID(第 2 列)。对于每个人,记录了 7 个不同的测量值(第 3-9 列)。将这么多值手动输入数据库后,我确定会出现一些拼写错误并产生异常值,例如,应该读取 15.2 的测量值可能输入为 1.52 或 152 或 25.2。我想找出那些异常值,这样我就可以修复它们而不是将它们丢弃,但是有太多的物种无法根据具体情况进行处理。我如何自动化和组织对每个物种的每个测量子集的离群值搜索的输出?最后一部分很关键,因为每个物种的大小可能不同,测量值也大不相同。我正在尝试尽可能地简化,因为每次将新一批数据添加到数据库时(或者直到有人申请 filemaker 许可证),这可能会完成。
我在 R 中进行分析。我认为对于所有超出均值 2 或 3 个标准差的值的嵌套 for 循环就可以解决问题,and/or group_by 使用 dplyr 和分位数功能。但是我一直无法弄清楚如何在返回实际异常值的同时 运行 所有列。还有许多其他问题可以解决其中的一些问题,但我找不到将所有问题放在一起的问题。
示例数据:
df = data.frame(
species = c("a","b","a","b","a","b","a","b","a","b"),
uniqueID = c("x01","x02","x03","x04","x05","x06","x07","x08","x09","x10"),
metric1 = c(1,2,3,1,2,3,1,2,3,11),
metric2 = c(4,5,6,4,5,6,55,4,5,6),
metric3 = c(0.7,7,8,9,7,8,9,77,8,9)
)
就预期结果而言,我正在设想一个 data.frame 或矩阵报告物种,unique_ID,measurement/column 具有离群值,以及离群值本身。但是如何格式化并不重要,例如:
outliers = data.frame(
species = c("a","a","b","b"),
uniqueID = c("x01","x07","x08","x10"),
var = c("metric3","metric2","metric3","metric1"),
value = c(0.7,55,77,11)
)
提前致谢!
从您提供的数据开始...
df = data.frame(
species = c("a","b","a","b","a","b","a","b","a","b"),
uniqueID = c("x01","x02","x03","x04","x05","x06","x07","x08","x09","x10"),
metric1 = c(1,2,3,1,2,3,1,2,3,11),
metric2 = c(4,5,6,4,5,6,55,4,5,6),
metric3 = c(0.7,7,8,9,7,8,9,77,8,9)
)
我将在这里大量使用 tidyverse
...
library(tidyverse)
然后将行数增加三倍,这样标准偏差计算就不会死在我们身上,并添加另一个离群值行...
df2 <- df %>%
bind_rows(df) %>%
bind_rows(df) %>%
add_row(
species = "a",
uniqueID = "x01",
metric1 = 1,
metric2 = 4,
metric3 = 1e12
)
如果你尝试这样的事情会怎样?
df2 %>%
gather(key = "metric", value = "value", -species, -uniqueID) %>%
group_by(species, uniqueID, metric) %>%
arrange(species, uniqueID, metric) %>% # just to make the results easy to scan
mutate(
mean_obs = mapply(function(x) mean(value[-x]), 1:n()),
stdev = mapply(function(x) sd(value[-x]), 1:n()),
minimum = mean_obs - stdev * 2,
maximum = mean_obs + stdev * 2,
outlier = value < minimum | value > maximum
) %>%
filter(outlier) %>%
glimpse()
借鉴
如果您排除当前记录并且该记录不是异常值,它会变得很奇怪,它会明显改变平均值和标准偏差。但是如果记录 是 一个离群值,你肯定想这样做。 :)