【问题标题】:r return common rows for each value in a given columnr 返回给定列中每个值的公共行
【发布时间】:2015-01-28 21:10:42
【问题描述】:

假设我有一个看起来像这样的数据框:

    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

我知道这个问题是基本的,而且可能以前有人问过;但是我的方法太长了,我确信有一种更有效的方法:我曾经根据类别拆分数据框,并进行设置交集。请问有没有更好的办法?谢谢!

【问题讨论】:

  • 你知道分类的数量吗,有没有可能一个类型在一个分类中出现多次?从上面的示例中,您知道绿色出现在每个类别中,因为它出现了 3 次,但我不确定这是否适用于您的实际数据。
  • @Joe 我保证一个类型在任何给定类别中不会出现多次

标签: r dataframe set-operations


【解决方案1】:

假设type 最多出现在category 中一次(否则将== 更改为>=)并使用table 您可以尝试以下操作:

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

【讨论】:

  • 不错的一个。 +1 如果您添加一些解释。
【解决方案2】:

这是使用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,这可以通过利用uniqueN 函数的data.table 的更新版本更简洁地完成:

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)

【讨论】:

  • 愿意为不懂data.table语法的人解释一下代码吗?
  • @nico 是的,很抱歉,正如您评论的那样,我正在扩展我的答案。
  • 不错!只是另一种方式:unique(dt)[, .N, by=type][N == uniqueN(dt$category), type]uniqueN 是 1.9.5 中的新版本,是 length(unique(.)) 的更快版本。
  • @Arun 谢谢!我现在使用的机器有一个旧版本的 R / data.table,但我肯定会在我的另一台电脑上使用它。
【解决方案3】:

我真的找不到一个非常明显的解决方案,但这确实有效。

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

【讨论】:

    【解决方案4】:

    如果df 是您的data.frame,这里是“一”行代码,感谢Reduce

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

    【讨论】:

    【解决方案5】:

    一种方法是制作一个表格,然后选择出现每个类别出现次数的类型(在本例中为 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
    

    【讨论】:

      【解决方案6】:

      假设你的数据在df:

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

      这将计算每种类型的出现次数,并查看哪些出现的次数与您拥有的类别一样多。如果类型在一个类别中出现的次数不超过一次,它将有效地执行您想要的操作,但如果违反该假设,它将无法工作。

      【讨论】:

      • 嗨,乔,请问聚合函数的包是什么?谢谢!
      • @maryam 默认加载,它来自stats 包。我怎么知道?在 R 中,我输入了?aggregate。如果它没有产生任何结果,我可以尝试??aggregate,如果这也不起作用RSiteSearch("aggregate")
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-10-18
      • 1970-01-01
      • 1970-01-01
      • 2022-11-28
      • 2021-12-12
      • 2016-01-28
      • 1970-01-01
      相关资源
      最近更新 更多