代码之家  ›  专栏  ›  技术社区  ›  conor

当组合不存在时,用空值重新整形

  •  1
  • conor  · 技术社区  · 7 年前

    我有一些数据 melt dcast 使用 reshape2 包装,如下所示。

    dat <- data.frame(Name = c("Alice", "Alice", "Alice", "Alice", "Bob", "Bob", "Bob"),
                  Month = c(1, 1, 1, 2, 1, 2, 2),
                  Product = c("Car", "Bike", "Car", "Car", "Car", "Bike", "Bike"),
                  Price = c(1000, 150, 300, 500, 2000, 200, 100))
    #    Name Month Product Price
    # 1 Alice     1     Car  1000
    # 2 Alice     1    Bike   150
    # 3 Alice     1     Car   300
    # 4 Alice     2     Car   500
    # 5   Bob     1     Car  2000
    # 6   Bob     2    Bike   200
    # 7   Bob     2    Bike   100
    
    dat_melt <- melt(dat, id=c("Name", "Month", "Product"))
    #    Name Month Product variable value
    # 1 Alice     1     Car    Price  1000
    # 2 Alice     1    Bike    Price   150
    # 3 Alice     1     Car    Price   300
    # 4 Alice     2     Car    Price   500
    # 5   Bob     1     Car    Price  2000
    # 6   Bob     2    Bike    Price   200
    # 7   Bob     2    Bike    Price   100
    
    dat_spread <- dcast(dat_melt, Name + Month ~ Product + variable, value.var="value", fun=sum)
    #    Name Month Bike_Price Car_Price
    # 1 Alice     1        150      1300
    # 2 Alice     2          0       500
    # 3   Bob     1          0      2000
    # 4   Bob     2        300         0
    

    如何获得此输出,以便在名称月份产品组合不存在的情况下(例如Alice,2,Bike)返回 NULL NA 而不是 0 ?注意,解决方案应适用于以下情况: Price 为0,因此,例如。 dat_spread$BikePrice[BikePrice == 0] <- NA 不可接受。

    我尝试在中使用匿名函数 dcast 无济于事,例如。

    library(dplyr)
    dcast(dat_melt, Name + Month ~ Product + variable, value.var="value",
          fun.aggregate = function(x) if_else(is.na(x), NULL, sum(x)))
    #  Error: `false` must be type NULL, not double 
    
    dcast(dat_melt, Name + Month ~ Product + variable, value.var="value",
          fun.aggregate = function(x) if_else(is.na(x), 3.14, sum(x))) # then update after
    # Error in vapply(indices, fun, .default) : values must be length 0,
    # but FUN(X[[1]]) result is length 1
    

    笔记 重塑2 不是一项要求,因此如果您有一个不使用它的解决方案(例如使用 tidyverse 功能)那也太好了。

    2 回复  |  直到 7 年前
        1
  •  2
  •   Mikko Marttila    7 年前

    可以在中指定用于缺少组合的值 dcast 使用 fill 参数:

    dcast(dat_melt, Name + Month ~ Product + variable,
          value.var = "value", fun = sum, fill = NA_real_)
    #>    Name Month Bike_Price Car_Price
    #> 1 Alice     1        150      1300
    #> 2 Alice     2         NA       500
    #> 3   Bob     1         NA      2000
    #> 4   Bob     2        300        NA
    

    创建日期:2018年3月7日 reprex package (v0.2.0)。

    (注意,发动机罩下, dcast 呼叫 vapply ,对类型很挑剔;所以只需指定 fill = NA 还不够好 typeof(NA) == "logical" 并且您的值是数字的:您必须显式使用“double”NA NA_real_ )

        2
  •  1
  •   Maurits Evers    7 年前

    另一种选择是:您还可以使用 dplyr + tidyr :

    library(dplyr);
    library(tidyr);
    dat %>%
        group_by(Name, Month, Product) %>%
        summarise(Price = sum(Price)) %>%
        spread(Product, Price);
    ## A tibble: 4 x 4
    ## Groups:   Name, Month [4]
    #  Name  Month  Bike   Car
    #  <fct> <dbl> <dbl> <dbl>
    #1 Alice    1.  150. 1300.
    #2 Alice    2.   NA   500.
    #3 Bob      1.   NA  2000.
    #4 Bob      2.  300.   NA
    

    类似于 dcast ,则, spread 有一个 fill 参数,即 fill=NA 默认情况下。