R: Удалить все значения с менее чем 3 выборками, метод подсчета без включения NA

У меня есть кадр данных в образце файла .csv, который выглядит так.

NAME;   ID; REFERENCE_YEAR; VALUE
FORGOTTEN COL;  2282;   1987;   NA
FORGOTTEN COL;  2282;   1998;   NA
FORGOTTEN COL;  2282;   1999;   NA
FORGOTTEN COL;  2282;   2008;   NA
FORGOTTEN COL;  2282;   2010;   -48
FOX;    1536;   1894;   -140
FOX;    1536;   1934;   -480
FOX;    1536;   1955;   -280
FOX;    1536;   1956;   -1420
FOX;    1536;   1965;   180
FOX;    1536;   1967;   20
BURTON; 1606;   1996;   NA
BURTON; 1606;   1997;   NA
BURTON; 1606;   1998;   NA
BURTON; 1606;   1999;   NA
BURTON; 1606;   2007;   NA
BURTON; 1606;   2010;   0
BREWSTER;   1597;   1997;   -98
BREWSTER;   1597;   2005;   -8
AMARILLO;   233;    1936;   NA
AMARILLO;   233;    1937;   NA
AMARILLO;   233;    1938;   NA
BETA;   244;    2006;   NA
BETA;   244;    2007;   NA
BETA;   244;    2008;   NA
BETA;   244;    2009;   NA

Вы также можете найти файл .csv здесь: https://dl.dropboxusercontent.com/u/16277659/test_count.csv

Что я хочу сделать с этим в R: я хотел бы отфильтровать все ЗНАЧЕНИЯ, которые имеют менее трех измерений (ЗНАЧЕНИЯ), на основе всей группы ИМЯ, и удалить их из фрейма данных. Я пока использую следующий код:

df <- read.csv("test_count.csv", sep=";", header=TRUE)

z <- table(df$NAME)
df <- df[df$NAME %in% names(z)[z >3],]

Проблема в том, что с помощью этого метода учитываются также NA в VALUE, чего я не хочу (например, в FORGOTTEN COL единственное значение, которое должно быть подсчитано, это -48, в BURTON это 0), и поэтому группы должны быть удалены из фрейма данных.

Есть ли способ сделать это и исключить значения NA из условного оператора? Исключение: когда есть только значения NA, как в AMARILLO, они также должны быть удалены. Любая помощь приветствуется.


person kurdtc    schedule 07.08.2014    source источник
comment
Для этого должно быть достаточно изменить table(df$NAME) на table(df$NAME[!is.na(df$VALUE)]) (за счет исключения NA из подсчета).   -  person talat    schedule 07.08.2014


Ответы (3)


Вы можете подсчитать количество не-NA по ("by"!) NAME, используя by():

foo <- with(df,by(VALUE,NAME,function(xx)sum(!is.na(xx))))
foo

Эти ИМЕНА имеют по крайней мере три не-NA:

names(which(foo>=3))

Итак, вы хотите:

df[df$NAME %in% names(which(foo>=3)),]
person Stephan Kolassa    schedule 07.08.2014

Вот решение с использованием dplyr.

Сначала прочитайте данные, используя read.csv2():

dat <- read.csv2("https://dl.dropboxusercontent.com/u/16277659/test_count.csv")

Затем используйте два фильтра для данных:

  • первый фильтр удаляет NA значения
  • второй удаляет все строки, где количество строк ‹ 3

Попробуй это:

library(dplyr)
dat %>% group_by("NAME") %>% filter(!is.na(VALUE)) %>% filter(length(VALUE)>=3)

Source: local data frame [6 x 4]
Groups: NAME

  NAME   ID REFERENCE_YEAR VALUE
1  FOX 1536           1894  -140
2  FOX 1536           1934  -480
3  FOX 1536           1955  -280
4  FOX 1536           1956 -1420
5  FOX 1536           1965   180
6  FOX 1536           1967    20
person Andrie    schedule 07.08.2014

df[with(df, ave(VALUE, NAME, FUN=function(x) sum(!is.na(x))))>=3,] 
 #   NAME   ID REFERENCE_YEAR VALUE
 #6   FOX 1536           1894  -140
 #7   FOX 1536           1934  -480
 #8   FOX 1536           1955  -280
 #9   FOX 1536           1956 -1420
 #10  FOX 1536           1965   180
 #11  FOX 1536           1967    20

Или по вашему методу

z <- table(!is.na(df$VALUE), df$NAME)[2,] ##change 
df[df$NAME %in% names(z)[z >= 3],]
#   NAME   ID REFERENCE_YEAR VALUE
#6   FOX 1536           1894  -140
#7   FOX 1536           1934  -480
#8   FOX 1536           1955  -280
#9   FOX 1536           1956 -1420
#10  FOX 1536           1965   180
#11  FOX 1536           1967    20
person akrun    schedule 07.08.2014