2016-08-25 3 views
0

Я хотел бы создать подмножество большого фрейма данных на основе двух столбцов Cola и ColB (см. Ниже). Для каждой переменной в ColA (например, A, B, C ...) я хотел бы извлечь строки, соответствующие каждому вхождению первой переменной в ColB. Поэтому DF1:R подмножество строк для всех вхождений первой переменной в столбец

ColA ColB ColC 
A  Red  7thing 
A  Red  OneBot 
A  Blue BotOne 
B  Green Thing7 
B  Green Twosies 
B  Green Square 
B  Yellow Circle 
B  Yellow Polygon 
B  Purple Triangle 
B  White Octagon 
C  Orange Cube 
C  Black Line 

стал бы DF2:

ColA ColB ColC 
A  Red  7thing 
A  Red  OneBot 
B  Green Thing7 
B  Green Twosies 
B  Green Square 
C  Orange Cube 

Я не обеспокоен дублей в ColC, и нет никакой закономерности числу вхождений переменной в ColB. Связанные стратегии подмножества, которые я нашел, сосредоточены на извлечении уникальных случаев, но я не нашел и не смог разработать подход, позволяющий выбрать все вхождения первого типа переменной и был бы благодарен за некоторую помощь.

Я попытался

DF2 <- DF1[match(unique(DF1$ColB), DF1$ColB),] 

... и Подменят, который нацелен на переменном, когда содержимое переменного известно (например, Subset first n occurrences of certain value in dataframe in R), они не подходят по-видимому.

+1

какой код вы пробовали? SO - ресурс кодирования, а не служба кодирования. – Nate

+0

Я отредактировал свое сообщение, чтобы включить некоторый код, и мог бы добавить больше, если это полезно, но проблема не является ошибкой в ​​соответствующем коде, поэтому я ее не включил. Извинения, если мой вопрос натолкнулся на ожидание службы, это не так, рекомендации SO, как представляется, включают в себя код, который не подходит для каждого вопроса, и это то, что я использовал в качестве моего руководства. – SPZ

ответ

5

Сила ave в базе R, сравнить все ColB дела в первой ColB в каждой группе:

dat[with(dat, ColB == ave(ColB, ColA, FUN=function(x) head(x,1))),] 

# ColA ColB ColC 
#1  A Red 7thing 
#2  A Red OneBot 
#4  B Green Thing7 
#5  B Green Twosies 
#6  B Green Square 
#11 C Orange Cube 

Используя исходную логику, вы можете также merge назад на не-дублируется записей только ColA/ColB:

merge(dat, dat[c("ColA","ColB")][!duplicated(dat$ColA),]) 
+0

Замечательно, спасибо, что вы указали тактику слияния. – SPZ

2

Вы можете использовать dplyr сделать то, что вы хотите:

library(dplyr) 
df2 <- df1 %>% group_by(ColA) %>% filter(ColB == first(ColB)) 

Первый group_byColA, затем filter держать только те строки, где ColB равно значению first в ColB. Результаты с использованием ваших данных:

print(df2) 
##Source: local data frame [6 x 3] 
##Groups: ColA [3] 
## 
## ColA ColB ColC 
## <fctr> <fctr> <fctr> 
##1  A Red 7thing 
##2  A Red OneBot 
##3  B Green Thing7 
##4  B Green Twosies 
##5  B Green Square 
##6  C Orange Cube 
+0

Понятия не имею, почему вы ниспровергаетесь ?! Это прекрасно работает. – thelatemail

+0

@thelatemail: спасибо за поддержку! Пока ОП получает то, что он/она ищет, я хороший. – aichao

+0

Спасибо aichao и thelatemail, этот подход group_by прост и полезен! – SPZ

3

Другой подход с aggregate

df[df$ColB %in% unlist(aggregate(ColB~ColA, df, function(x) head(x, 1))[2]), ] 

# ColA ColB ColC 
#1  A Red 7thing 
#2  A Red OneBot 
#4  B Green Thing7 
#5  B Green Twosies 
#6  B Green Square 
#11 C Orange Cube 
3

Как это большой набор данных, подходы с использованием data.table являются

library(data.table) 
setDT(df1)[df1[, .I[ColB==ColB[1L]], ColA]$V1] 
# ColA ColB ColC 
#1: A Red 7thing 
#2: A Red OneBot 
#3: B Green Thing7 
#4: B Green Twosies 
#5: B Green Square 
#6: C Orange Cube 

Или с .SD

setDT(df1)[, .SD[ColB==ColB[1L]], ColA]