2017-07-07 2 views
3

Ich arbeite mit einem Datenrahmen, der sich mit numerischen Messungen beschäftigt. Einige Individuen wurden mehrmals gemessen, sowohl als Jugendliche als auch als Erwachsene. Ein reproduzierbares Beispiel:Subset-Datenrahmen, der nur Ebenen eines Faktors enthält, die Werte in beiden Ebenen eines anderen Faktors haben

ID <- c("a1", "a2", "a3", "a4", "a1", "a2", "a5", "a6", "a1", "a3") 
age <- rep(c("juvenile", "adult"), each=5) 
size <- rnorm(10) 

# e.g. a1 is measured 3 times, twice as a juvenile, once as an adult. 
d <- data.frame(ID, age, size) 

Mein Ziel ist es, dass der Datenrahmen der Teilmenge durch die IDs auszuwählen, die mindestens einmal als juveniles erscheinen und mindestens einmal als Erwachsene. Nicht sicher, wie das geht ..?

Der resultierende Datenrahmen würde alle Messungen für die Individuen a1, a2 und a3 enthalten, würde aber a4, a5 und a6 ausschließen, da sie nicht in beiden Stufen gemessen wurden.

Eine ähnliche Frage wurde vor 7 Monaten gefragt hatte aber nie eine Antwort (Subset data frame to include only levels one factor that have values in both levels of another factor)

Dank!

Antwort

3

Hier ist eine Option, mit data.table

library(data.table) 
setDT(d)[, .SD[all(c("juvenile", "adult") %in% age)], ID] 

Oder eine base R Option mit ave

d[with(d, ave(as.character(age), ID, FUN = function(x) length(unique(x)))>1),] 
# ID  age  size 
#1 a1 juvenile -1.4545407 
#2 a2 juvenile -0.4695317 
#3 a3 juvenile 0.2271316 
#5 a1 juvenile 0.2961210 
#6 a2 adult -0.8331993 
#9 a1 adult -0.6924967 
#10 a3 adult -0.4619550 
4

Mit dplyr können Sie group_by %>% filter verwenden:

library(dplyr) 
d %>% group_by(ID) %>% filter(all(c("juvenile", "adult") %in% age)) 

# A tibble: 7 x 3 
# Groups: ID [3] 
#  ID  age  size 
# <fctr> <fctr>  <dbl> 
#1  a1 juvenile -0.6947697 
#2  a2 juvenile -0.3665272 
#3  a3 juvenile 1.0293555 
#4  a1 juvenile 0.2745224 
#5  a2 adult 0.5299029 
#6  a1 adult 2.2247802 
#7  a3 adult -0.4717160 
4

split von age, intersect und Untergruppe:

d[d$ID %in% Reduce(intersect, split(d$ID, d$age)),] 
# ID  age  size 
#1 a1 juvenile 1.44761836 
#2 a2 juvenile 1.70098645 
#3 a3 juvenile 0.08231986 
#5 a1 juvenile 0.91240568 
#6 a2 adult -1.77318962 
#9 a1 adult 0.13597986 
#10 a3 adult -1.18575294 
Verwandte Themen