2016-11-22 5 views
1

Я новый пользователь R, и это мой первый вопрос (надеюсь, в соответствии с протоколом).Подмножество фрейма данных R на основе порогового значения частоты столбца

У меня есть кадр данных с двумя столбцами.

df <- data.frame(v1 = c("A", "A", "B", "B", "B", "B", "C", "D", "D", "E")) 
dfc <- df %>% count(v1) 
df$n <- with(dfc, n[match(df$v1,v1)]) 

    v1 n 
1 A 2 
2 A 2 
3 B 4 
4 B 4 
5 B 4 
6 B 4 
7 C 1 
8 D 2 
9 D 2 
10 E 1 

Я хочу удалить строки, которые превышают порог 3 вхождений для значения в v1. Все строки для этого значения меньше порога сохраняются. В этом примере я хочу удалить строку 6 и сохранить все остальные строки в кадре данных подмножества.

Результат будет включать следующие значения для v1:

v1 
1 A 
2 A 
3 B 
4 B 
5 B 
6 C 
7 D 
8 D 
9 E 

Ряд 6 был бы удален, поскольку он был 4-возникновение «B», но 3 предыдущие строки для «B» были сохранены ,

Я прочитал несколько сообщений, которые демонстрируют, как удалить все строки для переменной с строк составляет меньше/больше, чем кумулятивное значение частоты, такие как 4. Например, я попытался:

df1 <- df %>% 
    group_by(v1) %>% 
    filter(n() < 4) 

В этом подход сохраняет только строки, где все уникальные вхождения V1 равны < 4. 6 строк являются подмножествами.

df2 <- df %>% 
    group_by(v1) %>% 
    filter(n() > 3) 

Этот подход содержит только строки, в которых все уникальные вхождения v1 являются> 3. 4 строки являются подмножествами.

df4 <- subset(df, v1 %in% names(table(df$v1))[table(df$v1) <4]) 

Этот подход имеет тот же результат, что и первый подход.

Ни один из этих методов не дает результат, который мне нужен.

Как было сказано ранее, мне нужно сохранить первые три строки, где v1 = «B», и удалять только строки, если есть 3 вхождения этого значения.

Поскольку я новичок в R, возможно, я пропустил очень простое решение. Любые предложения будут ценны.

Спасибо.

ответ

1

Использование dplyr-х top_n:

df %>% group_by(v1) %>% top_n(3) 
+0

Ну ... это было намного проще, чем мое решение , – William

+0

Jacob - Спасибо за решение. Он отлично работал. – danbret

0

Мы можем использовать data.table

library(data.table) 
setDT(df)[, if(.N >3) head(.SD, 3) else .SD , v1] 
0

Это, кажется, сделать это:

index <- vector("numeric", nrow(df)) 

for (i in 1:nrow(df)) { 
    if (sum(df[1:i, ] == as.character(df[i, 1])) <= 3) { 

    index[i] <- i 

    } else { 

    cat(i) 
    } 

} 


df[index, ] 
    v1 n 
1 A 2 
2 A 2 
3 B 4 
4 B 4 
5 B 4 
7 C 1 
8 D 2 
9 D 2 
10 E 1 
Смежные вопросы