уменьшить фрейм данных, чтобы получить равное количество строк на значение (по группе) - PullRequest
0 голосов
/ 19 июня 2020

Предположим, у меня есть следующий набор данных:

id <- c("vp01","vp01","vp01","vp01", "vp02", "vp02","vp02","vp02","vp02", "vp02")
rating <- c("0","1","0","0","1","0","1", "0", "0", "0")
Au1 <- c("150.0","100.45","80.23","133.21","94.33","102.22", "83.45", "122.65", "115.41", "109.34")

df <- data.frame(id,rating,Au1)


     id rating    Au1
1  vp01      0  150.0
2  vp01      1 100.45
3  vp01      0  80.23
4  vp01      0 133.21
5  vp02      1  94.33
6  vp02      0 102.22
7  vp02      1  83.45
8  vp02      0 122.65
9  vp02      0 115.41
10 vp02      0 109.34

В моем наборе данных гораздо больше 0, чем 1. Я хотел бы удалить строки таким образом, чтобы в каждом идентификаторе совпадало количество оценок 0 количество 1 оценок. Количество строк на идентификатор может отличаться. Результат может выглядеть так.

Ответы [ 2 ]

3 голосов
/ 19 июня 2020

Добавьте столбец подсчета для каждого id и rating, затем для каждого id выберите минимальное значение подсчета и для каждого id и rating выберите это минимальное количество строк.

library(dplyr)

df %>%
  add_count(id, rating) %>%
  group_by(id) %>%
  mutate(n = min(n)) %>%
  group_by(rating, .add = TRUE) %>%
  #In old dplyr add = TRUE
  #group_by(rating, add = TRUE) %>%
  sample_n(n) %>%
  select(-n)


#  id    rating Au1   
#  <chr> <chr>  <chr> 
#1 vp01  0      133.21
#2 vp01  1      100.45
#3 vp02  0      102.22
#4 vp02  0      115.41
#5 vp02  1      83.45 
#6 vp02  1      94.33 

Я использую sample_n здесь, чтобы выбрать любые случайные n строки для id и rating. Это можно изменить, если у вас есть какие-либо предпочтения. Например, мы можем выбрать первые n строк, последние n строк или строки на основе значения Au1 столбца.

0 голосов
/ 19 июня 2020

Решение Base R:

# Create a grouping vector to split on in order to remove duplicates:
# group => character vector
df$group <- paste0(df$id, unlist(sapply(split(df, df$id), function(y){
        cumsum(c(TRUE, abs(diff(as.numeric(y$rating)))))
      }
    )
  )
)

# Remove data duplicated within groups: data.frame => stdout (console)
data.frame(do.call("rbind", lapply(split(df, df$group), function(x){
        x[!duplicated(x$group), c("id", "rating", "Au1")]
      }
    )
  ),
row.names = NULL)

Вывод:

#    id rating    Au1
#1 vp01      0  150.0
#2 vp01      1 100.45
#3 vp01      0  80.23
#4 vp02      1  94.33
#5 vp02      0 102.22
#6 vp02      1  83.45
#7 vp02      0 122.65
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...