У меня есть очень большой фрейм данных с видами рыб в одной из колонок. Вот очень сокращенный пример:

ID = seq(1,50,1)

fishes = c("bass", "jack", "snapper")
common = sample(fishes, size = 50, replace = TRUE)

dat = as.data.frame(cbind(ID, common))

Я хочу удалить любые виды, которые составляют менее определенного процента данных. Например, здесь я хочу удалить все виды, которые составляют менее 30% данных:

library(dplyr)
nrow(filter(dat, common == "bass"))      #22 rows -> 22/50 -> 44%
nrow(filter(dat, common == "jack"))      #12 rows -> 12/50 -> 24%
nrow(filter(dat, common == "snapper"))   #16 rows -> 16/50 -> 32%

Здесь гнезда составляют менее 30% рядов, поэтому я хочу удалить все ряды с помощью гнезд (или всех видов с менее чем 15 рядами). Это легко сделать здесь, но на самом деле у меня есть более 700 видов рыб в моем фрейме данных, и я хочу выбросить все виды, которые составляют менее 1% данных (что в моем случае было бы менее 18 003 строк) , Есть ли рациональный способ сделать это без необходимости отфильтровывать каждый вид отдельно?

Я представляю, возможно, какой-то цикл, который говорит, что если число строк для общего имени = "x" меньше 18003, удалите эти строки ...

0
FishMasterB 27 Апр 2020 в 17:14

2 ответа

Лучший ответ

Вы также можете сделать это в одной трубе:

library(dplyr)

dat %>%
  mutate(percentage = n()) %>%
  group_by(common) %>%
  mutate(percentage = n() / percentage) %>%
  filter(percentage > 0.3) %>%
  select(-percentage)
3
Piotr K 27 Апр 2020 в 14:42

Один из способов сделать это - сначала создать сводную таблицу, а затем выполнить фильтрацию на основе сводной статистики. Вероятно, есть более прямые способы сделать то же самое.

library(dplyr)
set.seed(914) # so you get the same results from sample()

ID = seq(1,50,1)

fishes = c("bass", "jack", "snapper")
common = sample(fishes, size = 50, replace = TRUE)

dat = as.data.frame(cbind(ID, common))  # same as your structure, but I ended up with different species mix

summ.table <-  dat %>%
      group_by(common) %>%
      summarize(number = n()) %>%
      mutate(pct= number/sum(number))
summ.table
# # A tibble: 3 x 3
# common  number   pct
# <fct>    <int> <dbl>
# 1 bass        18  0.36
# 2 jack        18  0.36
# 3 snapper     14  0.28

include <- summ.table$common[summ.table$pct > .3]

dat.selected = filter(dat, common %in% include)

2
Brian Fisher 27 Апр 2020 в 14:35