r возвращает общие строки для каждого значения в данном столбце

При условии, что у меня есть датафрейм, который выглядит так:

    category  type
[1] A        green
[2] A        purple
[3] A        orange
[4] B        yellow
[5] B        green
[6] B        orange
[7] C        green

Как я могу получить список, содержащий те типы, которые появляются в каждой категории? В этом случае это должно выглядеть так:

    type
[1] green

Я знаю, что этот вопрос является основным, и, вероятно, был задан кем-то еще раньше; но мой метод слишком длинный, и я уверен, что есть более эффективный способ сделать это: я использовал, чтобы разделить фрейм данных на основе категории, и сделать пересечение наборов. Есть ли лучший способ, пожалуйста? Спасибо!

6 ответов

Решение

Вот один подход, использующий data.table - при условии, что type появляется только один раз в каждой категории:

library(data.table)
DT <- data.table(DF)
##
R> DT[
    ,list(
      nCat=.N
    ),by=type][
      nCat==length(unique(DT$category)),
      type]
[1] "green"

Все это позволяет агрегировать исходные данные в виде количества строк по типу (nCat), а затем подмножество этого результата, взяв строки, где nCat равно уникальному количеству категорий в DT,

Изменить: Благодаря @Arun, это может быть сделано более кратко с новой версией data.table пользуясь преимуществом uniqueN функция:

unique(dt)[, .N, by=type][N == uniqueN(dt$category), type]

Если вы не гарантированы, что type появится не более одного раза в каждой категории, вы вносите небольшие изменения в вышеперечисленное:

R> DT[
    ,list(
      nCat=length(unique(category))
    ),by=type][
      nCat==length(unique(DT$category)),
      type]
[1] "green" 

Данные:

DF <- read.table(
  text="category  type
A        green
A        purple
A        orange
B        yellow
B        green
B        orange
C        green",
  header=TRUE,
  stringsAsFactors=F)

Предполагая type появляется в category максимум один раз (в противном случае измените == в >=) и используя table Вы можете попробовать следующее:

 colnames(table(df))[colSums(table(df)) == length(unique(df$category))]
[1] "green"

Одним из способов может быть создание таблицы и выбор типов, которые будут отображаться, сколько раз появляется каждая категория (в данном случае 3), или, поскольку вы говорите, что она может появляться только один раз, просто возьмите среднее и выберите среднее == 1 (или>= 1).

dat <- read.table(header = TRUE, text="category  type
A        green
A        purple
A        orange
B        yellow
B        green
B        orange
C        green")

tbl <- data.frame(with(dat, ftable(category, type)))
tbl[with(tbl, ave(Freq, type)) >= 1, ]

#   category  type Freq
# 1        A green    1
# 2        B green    1
# 3        C green    1

unique(tbl[with(tbl, ave(Freq, type)) >= 1, 'type'])
# [1] green

Если df твой data.frameвот одна строка кода благодаря Reduce:

x = df$category
y = df$type

Reduce(intersect, lapply(unique(x), function(u) y[x==u]))
#[1] "green"

Я не мог найти супер-очевидное решение, однако это делает работу.

df <- data.frame(category=c("A", "A", "A", "B", "B", "B", "C"), 
                 type=c("green", "purple", "orange", "yellow", 
                        "green", "orange", "green"))

# Split the data frame by type
# This gives a list with elements corresponding to each type
types <- split(df, df$type)

# Find the length of each element of the list
len <- sapply(types, function(t){length(t$type)})

# If the length is equal to the number of categories then 
# the type is present in all categories 
res <- names(which(len==length(unique(df$category))))

Обратите внимание, что sapply вернет типы как имена вектора, следовательно, вызов names в следующем заявлении.

Предполагая, что ваши данные находятся в df:

df.sum <- aggregate(df$tpye, by = list(df$type), FUN = length)
types <- df.sum[which(df$sum == length(unique(df$x))),]

Это будет подсчитывать количество появлений в каждом типе, и посмотреть, какие из них появляются столько раз, сколько у вас есть категории. Если типы не появляются более одного раза в категории, он будет эффективно делать то, что вы хотите, хотя он не будет работать, если это предположение нарушается.

Другие вопросы по тегам