【问题标题】:r reshape with nulls when combination doesn't existr 当组合不存在时用空值重塑
【发布时间】:2018-03-07 07:42:45
【问题描述】:

我有一些数据我meltdcast使用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)返回 NULLNA 而不是 0?请注意,该解决方案应该适用于 Price 为 0 的情况,例如dat_spread$BikePrice[BikePrice == 0] &lt;- 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

注意,reshape2 不是必需的,所以如果您有一个不使用它的解决方案(例如使用 tidyverse 函数),那也很好。

【问题讨论】:

    标签: r reshape tidyr reshape2


    【解决方案1】:

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

    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
    

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

    (请注意,在后台,dcast 调用 vapply,这对类型很挑剔;因此仅指定 fill = NA 还不够,因为 typeof(NA) == "logical" 并且您的值是数字:您必须明确使用 NA_real_ 的“双”NA)

    【讨论】:

      【解决方案2】:

      作为替代方案:您也可以使用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
      

      类似于dcastspread 有一个fill 参数,默认为fill=NA

      【讨论】:

      • 太棒了,感谢您的回答。旁注,您的双打是否像您的答案一样在小数点后面打印?我的指定 但打印与整数相同。这是你专门设置的吗?
      • 打印带小数点的双精度是最近发布的 new version of pillar 中的一项功能,该软件包控制 tibble 打印。
      • @MikkoMarttila 感谢您的澄清;我不知道。
      猜你喜欢
      • 1970-01-01
      • 2012-11-21
      • 1970-01-01
      • 1970-01-01
      • 2021-12-03
      • 1970-01-01
      • 2019-09-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多