【问题标题】:Wide dummies to long factor with expansion of rows随着行的扩展,从宽虚拟到长因子
【发布时间】:2016-12-12 19:28:42
【问题描述】:

在将数据从宽数据转换为长数据(反之亦然)方面存在许多资源。这里有一点转折,但如果我错过了任何现有答案,请告诉我。

不同之处在于我有一些由多个标志(虚拟变量)指示的行。我不仅需要从宽到长,还需要同时制作具有多个标志的行的副本。此外,虽然还有其他杂项数据,但没有唯一的 ID,因此没有“timevar”或“idvar”。

例子:

ds <- data.frame(other_data=c(1,2,3),flag_a = c(1,0,0), flag_b=c(0,1,0), flag_c=c(1,0,1))
ds
  other_data flag_a flag_b flag_c
1          1      1      0      1
2          2      0      1      0
3          3      0      0      1
desired_result <- data.frame(other_data=c(1,1,2,3), flag=c("a", "c","b","c"))
desired_result
  other_data flag
1          1    a
2          1    c
3          2    b
4          3    c

【问题讨论】:

  • 我认为 other_data 可以用作 id var..? library(data.table); melt(setDT(ds), id = "other_data", variable.factor = FALSE)[value == 1, .(other_data, substr(variable, nchar(variable), nchar(variable)))]
  • @Frank 在真实数据集中,其他数据就像 40 列非常不明确的数据,例如数百行的 4 个水平因子。那还能用吗?
  • 我可能预料到的唯一问题是,您将临时拥有一个包含所有这些零的行的对象,这可能会占用内存。不过,只有数百行和 40 个标志,我想它会没事的。顺便说一句,没有单独发布,因为它只是 MrFlick 答案的一个(不是很好的)变体。

标签: r


【解决方案1】:

您可以使用 tidyverse 重塑、过滤和变换

library(tidyverse)
gather(ds, flag, present, flag_a:flag_c) %>% 
  filter(present>0) %>% 
  separate(flag, c("pre","flag")) %>% 
  select(-present, -pre)

这会导致...

#   other_data flag
# 1          1    a
# 2          2    b
# 3          1    c
# 4          3    c

【讨论】:

    【解决方案2】:

    除非我误解了你想要的,你可以用dplyrtidyr::gather来做到这一点:

    library(dplyr)
    library(tidyr)
    res <- ds %>% gather("flag","value",-1) %>% 
                  filter(value != 0) %>% 
                  mutate(flag=sub("flag_","",flag)) %>% 
                  select(-value)
    ##  other_data flag
    ##1          1    a
    ##2          2    b
    ##3          1    c
    ##4          3    c
    

    我们gather 除第一列之外的所有列(即other_data)。我们首先filter 只保留value != 0 的行,然后我们使用subflag 中提取标志名称。最后,我们删除了value 列。

    【讨论】:

    • gather() 来自tidyr,而不是dplyr
    【解决方案3】:

    这是一个base R 选项来获取输出

    data.frame(other_data = rep(ds[,1], rowSums(ds[-1]!=0)),
           flag = sub(".*_", "", names(ds)[-1][t(ds[-1]*col(ds[-1]))]))
    #   other_data flag
    #1          1    a
    #2          1    c
    #3          2    b
    #4          3    c
    

    【讨论】:

      猜你喜欢
      • 2014-04-12
      • 2016-05-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-08-18
      • 1970-01-01
      • 2022-11-03
      相关资源
      最近更新 更多