Как использовать top_n для условного извлечения

Итак, у меня есть столбец (категория), который содержит «Да» или «Нет» в моем df, и для создания более сбалансированной выборки я хочу выбрать строки с первыми 500 случаями «Да» и первыми 500 случаями «Нет» из моего набора данных.

Я пробовал этот код:

top_n(df,500, category=="Yes")

Но это выбирает ВСЕ случаи да, а не только первые 500. Я также пробовал это, но это дало мне ошибку, хотя я уверен, что это не имеет смысла.

df %>% filter(top_n(500, category == "Yes") & top_n(500, category=="No")) Мне нужна небольшая помощь с правильным направлением


person Community    schedule 07.01.2021    source источник


Ответы (2)


Я бы, вероятно, просто использовал head для этого и отфильтровал непосредственно фрейм данных

df1 <- head(df[df$category == "Yes",], 500)
df2 <- head(df[df$category == "No",], 500)

# to combine
out <- rbind(df1, df2)

Я предполагаю, что top_n делает что-то подобное. Я ожидаю, что есть более приятный способ с dplyr, но это должно работать :)

person Jonny Phelps    schedule 07.01.2021
comment
Это отлично работает! Просто хотел найти способ заставить работать top_n или любой другой способ dplyr. Будем искать :) - person ; 07.01.2021
comment
top_n делает не то, что вы думаете. Если вы ищете ?top_n в консоли, она находит первые 500 строк по значению. Это важно, так как если у вас есть только одно значение в наборе данных, то выбор 1 строки будет иметь тот же эффект, что и выбор 5, например, top_n(data.frame(x=rep(1,10)), 5, "x") совпадает с top_n(data.frame(x=rep(1,10)), 10, "x") - person Jonny Phelps; 07.01.2021
comment
Существует dplyr версия head под названием glimpse, например stackoverflow.com/questions/23408510/ - person Jonny Phelps; 07.01.2021

Если вы хотите случайным образом выбрать ответы да/нет, вы можете использовать этот код:

#// generate toy data
df <- data.frame(YN = rep(c("yes", "no"),10), val = runif(20, 1, 100))
head(df)
#>    YN      val
#> 1 yes 26.00628
#> 2  no 98.34237
#> 3 yes 68.05788
#> 4  no 21.87011
#> 5 yes 33.92545
#> 6  no 68.74417

#// set random seed for reproducibility
set.seed(123)

#// randomly sample 5 'yes' answers
yes <- df[sample(which(df$YN == "yes"), 5),]
#// randomly sample 5 'no' answers
no <-  df[sample(which(df$YN == "no"), 5),]

#// create new dataframe with sampled answers
df_sub <- rbind(yes, no)
df_sub
#>     YN       val
#> 5  yes 33.925453
#> 19 yes 53.548253
#> 3  yes 68.057878
#> 15 yes 51.029700
#> 11 yes 91.768337
#> 10  no 11.923457
#> 8   no  8.467184
#> 12  no 63.233610
#> 16  no 93.375332
#> 2   no 98.342369

Создано 07 января 2021 г. с помощью пакета reprex (v0.3.0)

person Mario Niepel    schedule 07.01.2021
comment
Спасибо! Но я хотел создать сбалансированную выборку на основе первых 500 наблюдений за ответами «да» и «нет», так что это не случайность, но все равно спасибо за хороший пример! - person ; 07.01.2021
comment
Баланс достигается путем выборки одинаковых чисел для ответов «да» и «нет» (в данном примере число 5 в вызове sample — вы бы выбрали 500). Если есть предвзятость в том, как расположены ваши ответы, то, выбрав первые ответы, соответствующие вашим критериям поиска, вы можете внести эту предвзятость в свое подмножество и не получить сбалансированный набор. Но вы наверняка знаете свои данные лучше, чем кто-либо. - person Mario Niepel; 07.01.2021