【问题标题】:Reshaping wide format positive/negative data into long format binary outcome将宽格式正/负数据重塑为长格式二进制结果
【发布时间】:2023-03-18 20:51:01
【问题描述】:

我有数据可以查看来自特定农场的小母牛的妊娠试验结果。

例如。

Farm   Breed    Pregnant  Empty  Total  ADG
1      J        5         3      8      12
2      F        2         1      3      10
3      J        3         0      3      11

我希望怀孕和空数据成为二进制输出,而其他值只是重复

例如。

Farm   Breed  Pregnant  ADG
1      J      1         12
1      J      1         12
1      J      1         12
1      J      1         12
1      J      1         12
1      J      0         12
1      J      0         12
1      J      0         12
2      F      1         10
2      F      1         10
2      F      0         10

我一直在尝试使用重塑代码,但感到很困惑,想知道是否有人可以帮助我。

【问题讨论】:

    标签: r reshape


    【解决方案1】:

    我建议将“data.table”包与rep 结合使用。您希望通过 Pregnant 和 Empty 列中表示的数字重复值 1 和 0,因此您可以轻松地为此创建 rep 语句。默认情况下,行将“扩展”为您用来容纳新数据的keys。

    假设您从名为“mydf”的data.frame 开始,请尝试:

    library(data.table)
    as.data.table(mydf)[, list(Pregnant = rep(c(1, 0), c(Pregnant, Empty))), 
                        by = list(Farm, Breed, ADG)]
    #     Farm Breed ADG Pregnant
    #  1:    1     J  12        1
    #  2:    1     J  12        1
    #  3:    1     J  12        1
    #  4:    1     J  12        1
    #  5:    1     J  12        1
    #  6:    1     J  12        0
    #  7:    1     J  12        0
    #  8:    1     J  12        0
    #  9:    2     F  10        1
    # 10:    2     F  10        1
    # 11:    2     F  10        0
    # 12:    3     J  11        1
    # 13:    3     J  11        1
    # 14:    3     J  11        1
    

    我能想到的最接近的基本 R 方法是首先“扩展”源数据集的相关列(简单,使用 rep),然后使用 apply 获取“怀孕”的二进制结果,像这样:

    cbind(mydf[rep(rownames(mydf), mydf$Total), 
               c("Farm", "Breed", "ADG")], 
          Pregnant = unlist(apply(mydf[c("Pregnant", "Empty")], 1, 
                                  function(x) rep(c(1, 0), c(x[1], x[2])))))
    #     Farm Breed ADG Pregnant
    # 1      1     J  12        1
    # 1.1    1     J  12        1
    # 1.2    1     J  12        1
    # 1.3    1     J  12        1
    # 1.4    1     J  12        1
    # 1.5    1     J  12        0
    # 1.6    1     J  12        0
    # 1.7    1     J  12        0
    # 2      2     F  10        1
    # 2.1    2     F  10        1
    # 2.2    2     F  10        0
    # 3      3     J  11        1
    # 3.1    3     J  11        1
    # 3.2    3     J  11        1
    

    【讨论】:

    • 哦,这比我的rep, rep, rep, rep, rep方法好多了
    • @RichardScriven,我想不出比我的基本方法更少基于rep 的版本——我个人更喜欢“data.table”。
    • 这段代码运行良好,很容易应用到我的数据集中。非常感谢。
    【解决方案2】:

    以下是不言自明的:

    # repeat column values taking one row at a time and convert outcome list to a matrices:
    > m1 = matrix(unlist(apply(ddf[,c(1,2,3,6)], 1, function(x) rep(c(x[c(1,2,4)],1), x[3]))), nrow=4)
    > m2 = matrix(unlist(apply(ddf[,c(1,2,4,6)], 1, function(x) rep(c(x[c(1,2,4)],0), x[3]))), nrow=4)
    > 
    > 
    > m1
         [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
    [1,] "1"  "1"  "1"  "1"  "1"  "2"  "2"  "3"  "3"  "3"  
    [2,] "J"  "J"  "J"  "J"  "J"  "F"  "F"  "J"  "J"  "J"  
    [3,] "12" "12" "12" "12" "12" "10" "10" "11" "11" "11" 
    [4,] "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1"  "1"  
    
    > m2
         [,1] [,2] [,3] [,4]
    [1,] "1"  "1"  "1"  "2" 
    [2,] "J"  "J"  "J"  "F" 
    [3,] "12" "12" "12" "10"
    [4,] "0"  "0"  "0"  "0" 
    
    # combine, transpose and rename columns of matrices:
    > mm = t(cbind(m1, m2))
    > colnames(mm) = c('Farm','Breed','ADG','Preg_empty')
    > mm
          Farm Breed ADG  Preg_empty
     [1,] "1"  "J"   "12" "1"       
     [2,] "1"  "J"   "12" "1"       
     [3,] "1"  "J"   "12" "1"       
     [4,] "1"  "J"   "12" "1"       
     [5,] "1"  "J"   "12" "1"       
     [6,] "2"  "F"   "10" "1"       
     [7,] "2"  "F"   "10" "1"       
     [8,] "3"  "J"   "11" "1"       
     [9,] "3"  "J"   "11" "1"       
    [10,] "3"  "J"   "11" "1"       
    [11,] "1"  "J"   "12" "0"       
    [12,] "1"  "J"   "12" "0"       
    [13,] "1"  "J"   "12" "0"       
    [14,] "2"  "F"   "10" "0"       
    

    【讨论】:

    • 我觉得这根本不是“不言自明”。
    • 添加了一些解释。
    【解决方案3】:

    使用dplyr

    library(dplyr)
    library(tidyr)
    
     mydf %>%
       gather(Var, Val, Pregnant, Empty) %>% 
       mutate(N= row_number())%>%
       do(.[rep(.$N, .$Val),]) %>%
       select(Farm, Breed, ADG, Pregnant=Var) %>%
       mutate(Pregnant=c(1,0)[as.numeric(factor(Pregnant))]) %>%
       arrange(Farm, Breed)
    

    给出结果

      #    Farm Breed ADG Pregnant
      #1     1     J  12        1
      #2     1     J  12        1
      #3     1     J  12        1
      #4     1     J  12        1
      #5     1     J  12        1
      #6     1     J  12        0
      #7     1     J  12        0
      #8     1     J  12        0
      #9     2     F  10        1
      #10    2     F  10        1
      #11    2     F  10        0
      #12    3     J  11        1
      #13    3     J  11        1
      #14    3     J  11        1
    

    数据

     mydf <- structure(list(Farm = 1:3, Breed = c("J", "F", "J"), Pregnant = c(5L, 
     2L, 3L), Empty = c(3L, 1L, 0L), Total = c(8L, 3L, 3L), ADG = c(12L, 
     10L, 11L)), .Names = c("Farm", "Breed", "Pregnant", "Empty", 
     "Total", "ADG"), class = "data.frame", row.names = c(NA, -3L))
    

    【讨论】:

      【解决方案4】:

      试试melt

      require(reshape2)
      newdata<-melt(data[c(1:3,6)],id=c("Farm","Breed","Pregnant"))
      

      【讨论】:

      • 总是对你发布的答案进行一些解释,以便其他人可以轻松获得。
      • melt 是什么?是在一个包裹里吗? OP 应该知道在哪里可以找到它吗?
      • 当您的问题有解决方案时,只需花一点力气自己搜索即可。用勺子喂食不是一种好的学习方式。
      • chee.work.stuff:那条评论是发给@RichardScriven 的吗?如果您查看他的问题,您会发现他实际上比其他人可能愿意更深入地研究该语言。我认为您的评论不合适,而且您的回答似乎没有什么特别之处,只是删除了几列并转置了其他几列——绝对不是 OP 所要求的。
      猜你喜欢
      • 1970-01-01
      • 2012-02-18
      • 1970-01-01
      • 2017-07-19
      • 2021-05-01
      • 2021-09-15
      • 2022-01-11
      相关资源
      最近更新 更多