Usuwanie określonych wierszy z ramki danych
Mam ramkę danych np.:
sub day
1 1
1 2
1 3
1 4
2 1
2 2
2 3
2 4
3 1
3 2
3 3
3 4
I chciałbym usunąć konkretne wiersze, które można zidentyfikować po kombinacji sub i day. Na przykład powiedzmy, że chciałem usunąć wiersze, w których sub= '1'I day=' 2 'oraz sub=3 i day= '4'. Jak mogłem to zrobić? Zdaję sobie sprawę, że mogę określić numery wierszy, ale to musi być stosowane do ogromnej ramki danych, która byłaby żmudna, aby przejść i zidentyfikować każdy wiersz.
4 answers
DF[ ! ( ( DF$sub ==1 & DF$day==2) | ( DF$sub ==3 & DF$day==4) ) , ] # note the ! (negation)
Lub jeśli sub jest czynnikiem sugerowanym przez użycie cudzysłowów:
DF[ ! paste(sub,day,sep="_") %in% c("1_2", "3_4"), ]
Można też użyć podzbioru:
subset(DF, ! paste(sub,day,sep="_") %in% c("1_2", "3_4") )
(i popieram użycie which
w odpowiedzi Dirka podczas używania " [ " , mimo że niektórzy twierdzą, że nie jest to potrzebne.)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-30 19:50:26
Sprowadza się to do dwóch odrębnych kroków:
- Oblicz, kiedy twój warunek jest prawdziwy, a zatem Oblicz wektor wartości logicznych lub, jak wolę, ich indeksy, owijając go w
which()
- Utwórz zaktualizowany
data.frame
, wyłączając indeksy z poprzedniego kroku.
Oto przykład:
R> set.seed(42)
R> DF <- data.frame(sub=rep(1:4, each=4), day=sample(1:4, 16, replace=TRUE))
R> DF
sub day
1 1 4
2 1 4
3 1 2
4 1 4
5 2 3
6 2 3
7 2 3
8 2 1
9 3 3
10 3 3
11 3 2
12 3 3
13 4 4
14 4 2
15 4 2
16 4 4
R> ind <- which(with( DF, sub==2 & day==3 ))
R> ind
[1] 5 6 7
R> DF <- DF[ -ind, ]
R> table(DF)
day
sub 1 2 3 4
1 0 1 0 3
2 1 0 0 0
3 0 1 3 0
4 0 2 0 2
R>
I widzimy, że {[5] } został tylko jeden wpis z day==1
.
Edit warunek złożony można wykonać za pomocą " or " jako follows:
ind <- which(with( DF, (sub==1 & day==2) | (sub=3 & day=4) ))
A oto nowy pełny przykład
R> set.seed(1)
R> DF <- data.frame(sub=rep(1:4, each=5), day=sample(1:4, 20, replace=TRUE))
R> table(DF)
day
sub 1 2 3 4
1 1 2 1 1
2 1 0 2 2
3 2 1 1 1
4 0 2 1 2
R> ind <- which(with( DF, (sub==1 & day==2) | (sub==3 & day==4) ))
R> ind
[1] 1 2 15
R> DF <- DF[-ind, ]
R> table(DF)
day
sub 1 2 3 4
1 1 0 1 1
2 1 0 2 2
3 2 1 1 0
4 0 2 1 2
R>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-18 19:36:34
Oto rozwiązanie twojego problemu za pomocą funkcjifilter
dplyr .
Chociaż możesz przekazać ramkę danych jako pierwszy argument do dowolnej funkcji dplyr, użyłem jej operatora %>%
, który łączy ramkę danych do jednej lub więcej funkcji dplyr (po prostu filtruj w tym przypadku).
Po zapoznaniu się z dplyr, Ściągawka jest bardzo przydatna.
> print(df <- data.frame(sub=rep(1:3, each=4), day=1:4))
sub day
1 1 1
2 1 2
3 1 3
4 1 4
5 2 1
6 2 2
7 2 3
8 2 4
9 3 1
10 3 2
11 3 3
12 3 4
> print(df <- df %>% filter(!((sub==1 & day==2) | (sub==3 & day==4))))
sub day
1 1 1
2 1 3
3 1 4
4 2 1
5 2 2
6 2 3
7 2 4
8 3 1
9 3 2
10 3 3
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-09 13:15:46
Jedno proste rozwiązanie
cond1 <- df$sub == 1 & df$day == 2
cond2 <- df$sub == 3 & df$day == 4
df <- df[!cond1,]
df <- df[!cond2,]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-13 20:13:06