簡體   English   中英

通過因子水平和列識別R數據中的異常值

[英]Identifying outliers in R data by factor levels and columns

我有一個定期更新的生物數據庫,目前包含250個物種的13,500個個體的記錄(物種=第1欄中的因子水平)。 每個人都有一個唯一的ID(第2列)。 對於每個人,記錄了7種不同的測量值(第3-9列)。 由於手動輸入數據庫中的許多值,我確定發生了一些拼寫錯誤並創建了異常值,例如,應該讀取15.2的測量值可以輸入為1.52或152或25.2。 我想確定那些異常值,以便我可以修復它們而不是破壞它們,但是有太多的物種可以根據具體情況來做。 如何自動化和組織每個物種的每個測量子集的異常值搜索輸出? 最后一部分是至關重要的,因為每個物種可能是不同的尺寸,具有截然不同的測量值。 我正在嘗試盡可能地簡化,因為這可能是每次將新批數據添加到數據庫時(或者直到有人為文件制作者許可證提供)。

我在R中進行分析。我認為對於平均值的2或3個標准偏差之外的所有值的嵌套for循環將成功,和/或具有dplyr和分位數函數的group_by。 但是我還沒有弄清楚如何在返回實際異常值時一次運行所有列。 還有許多其他問題可以解決這個問題,但我找不到任何可以解決這個問題的問題。

示例數據:

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,帶有異常值的測量/列,以及異常值本身。 但是這種格式化的方式不那么重要,例如:

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,則將行標記為異常值。

如果排除當前記錄並且記錄不是異常值並且明顯改變平均值和標准偏差,則會變得奇怪。 但是如果記錄異常值,那么你肯定想要這樣做。 :)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM