【问题标题】:Subsetting rows in R, and filtering out rows if column has all-zero values for subset对 R 中的行进行子集化,如果列的子集的值全为零,则过滤掉行
【发布时间】:2017-07-31 23:58:49
【问题描述】:

这个问题是我最近(非常)问的问题here 的变体。 (很抱歉问了两个类似的问题。我问了之后才意识到我问的问题不太正确,但我想我会留下原来的,以防将来对人们有用,并将这个问题分开。)

我有一组看起来像这样的数据,对上一个问题稍作修改:

  Category     Item Shop1 Shop2 Shop3
1    Fruit   Apples     4     6     0
2    Fruit  Oranges     0     2     7
3      Veg Potatoes     0     1     0
4      Veg   Onions     0     2     8
5      Veg  Carrots     0     1     3
6    Dairy  Yoghurt     1     5     9
7    Dairy     Milk     0     1     0
8    Dairy   Cheese     0     0     7

我想过滤我的数据,以便我只有 所有 商店销售的类别 - 如果商店没有整个类别的任何销售,那么我想过滤出来。在此示例中,Veg 类别将被过滤掉,因为 Shop1 没有 Veg 销售。

为了解决这个问题,我尝试将针对上一个问题的建议从使用 FUN = any 更改为 FUN = all 但这不起作用并且每次都抛出错误,我不确定还有什么尝试。

如果您能提供任何帮助,我将不胜感激。

【问题讨论】:

  • 您可以尝试获取每个子集的总和,如果它等于 0,则进行过滤。我可以看到它是通过dplyr 包完成的。

标签: r


【解决方案1】:

这是colSums 的一个想法,

ind <- colSums(sapply(split(df[3:5], df$Category), function(i) colSums(i) == 0)) == 0
df[df$Category %in% names(ind)[ind],]

这给了,

 Category    Item Shop1 Shop2 Shop3
1    Fruit  Apples     4     6     0
2    Fruit Oranges     0     2     7
6    Dairy Yoghurt     1     5     9
7    Dairy    Milk     0     1     0
8    Dairy  Cheese     0     0     7

【讨论】:

  • rowSums:df[rowSums(sapply(df[,-(1:2)], function(a) ave(a, df$Category, FUN = sum) != 0)) == NCOL(df[,-(1:2)]),]
【解决方案2】:

这是一个使用dplyr 的示例。您首先group_by Category 变量,并且只保留销售超过 0 的记录。

library(tidyverse)
d <- data_frame(
    Category = c(rep("Fruit", 2), rep("Veg", 3), rep("Dairy", 3)),
    Item = c("Apples", "Oranges", "Potatoes", "Onions", "Carrots", "Yoghurt", "Milk", "Cheese"),
    Shop1 = c(4, rep(0, 4), 1, rep(0, 2)),
    Shop2 = c(6, 2, 1, 2, 1, 5, 1, 0),
    Shop3 = c(0, 7, 0, 8,  3, 9, 0, 7)
)

d %>%
    group_by(Category) %>%
    filter(sum(Shop1)  > 0 & sum(Shop2) > 0 &  sum(Shop3) > 0) %>%
    ungroup()

【讨论】:

    【解决方案3】:

    这是使用library(data.table)的解决方案

    dt <- data.table(category=c("Fruit","Fruit","Veg","Veg","Veg","Dairy","Dairy","Dairy"),
                                item=c("apples","oranges","potatoes","onions","carrots","yoghurt","milk","cheese"),
                                shop1=c(4,0,0,0,0,1,0,0),
                                shop2=c(6,2,1,2,1,5,1,0),
                                shop3=c(0,7,0,8,3,9,0,7))
    dt_m <- melt(dt,id.vars = c("category","item"))
    dt_m[,counts:=sum(value),by=.(category,variable)]
    dt_m <- dt_m[counts>0]
    dt_m[,counts:=NULL]
    dt <- dcast.data.table(dt_m,category+item~variable,value.var = "value")
    dt <- na.omit(dt)
    

    或使用dplyr

    dt %>% melt(id.vars = c("category","item")) %>% group_by(category,variable) %>%
      mutate(counts=sum(value)) %>% filter(counts>0) %>% mutate(counts=NULL) %>% 
      dcast(category+item~variable,value.var = "value") %>% na.omit()
    

    【讨论】:

      【解决方案4】:

      使用data.table 的另一种解决方案,使用两个步骤。

      # Data
      dt <- data.table(Category = c(rep("Fruit", 2), rep("Veg", 3), rep("Dairy", 3)),
                       Item     = c("Apples", "Oranges", "Potatoes", "Onions", 
                                    "Carrots", "Yoghurt", "Milk", "Cheese"),
                       Shop1    = c(4, rep(0, 4), 1, rep(0, 2)),
                       Shop2    = c(6, 2, 1, 2, 1, 5, 1, 0),
                       Shop3    = c(0, 7, 0, 8, 3, 9, 0, 7))
      
      filt <- dt[, any(sum(Shop1) == 0, sum(Shop2) == 0, sum(Shop3) == 0), 
                 by = Category]
      filt
             Category    V1
      1:    Fruit FALSE
      2:      Veg  TRUE
      3:    Dairy FALSE
      
      dt[Category %in% filt[V1 == FALSE, Category]]
      
         Category    Item Shop1 Shop2 Shop3
      1:    Fruit  Apples     4     6     0
      2:    Fruit Oranges     0     2     7
      3:    Dairy Yoghurt     1     5     9
      4:    Dairy    Milk     0     1     0
      5:    Dairy  Cheese     0     0     7
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-04-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多