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 с това: Бих искал да филтрирам всички СТОЙНОСТИ, които имат по-малко от три измервания (СТОЙНОСТИ) въз основа на цялата група от NAME и да ги изтрия от рамката с данни. Досега използвам следния код:

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 по ("от"!) NAME, като използвате by():

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

Тези NAMEs имат поне три не-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