【问题标题】:tidyr: transpose variables and fill blanks with zerostidyr:转置变量并用零填充空白
【发布时间】:2017-10-19 01:36:09
【问题描述】:

我有一个这样的数据框:

set.seed(456)
df <- data.frame(site = c(rep("Site1", 10), rep("Site2", 9)), 
                 genus = c(rep("sp1", 5), rep("sp2", 5), rep("sp1", 5), rep("sp2", 2), rep("sp3", 2)), 
                 abun = rnorm(19, 10,1))

我需要制作一个数据框,将因子site 的级别转换为变量。因此,site1site2 将成为一个变量,这些变量中的数据将是这些站点上genus 级别的abun 值。由于并非所有站点都具有相同的genus 或该属的相同数量的个体,因此没有物种或这些物种的代表很少的站点将用零填充。

本例中的数据将显示为:

output<- data.frame(genus = c(rep("sp1", 5), rep("sp2", 5), rep("sp3", 2)), 
                    site1 = c(9,22,74,86,79, 34,9,29,24,39,0,0), 
                    site2 = c(38,22,76,83,60, 66,85,0,0,0, 46,72)) 

我尝试了各种版本的 tidyverse mutate 或 reshape 函数,但无法获得所需的输出,也不知道如何获取零来填充空数据。

【问题讨论】:

    标签: r tidyverse


    【解决方案1】:

    由于您希望每个组中的索引是并行的,因此为每个组设置一个索引,您可以使用 dplyr::group_byrow_number 来执行此操作,之后传播将正常工作:

    library(tidyverse)
    set.seed(456)
    
    df<- data.frame( site= c(rep("Site1", 10), rep("Site2", 9)), 
                     genus= c(rep("sp1", 5), rep("sp2", 5), rep("sp1", 5), rep("sp2", 2), rep("sp3", 2) ), 
                     abun= rnorm(19, 10,1))
    
    df %>% 
        group_by(site) %>% 
        mutate(i = row_number()) %>%    # add row indices for each group
        spread(site, abun, fill = 0)
    #> # A tibble: 12 x 4
    #>     genus     i     Site1     Site2
    #>  * <fctr> <int>     <dbl>     <dbl>
    #>  1    sp1     1  8.656479  9.084189
    #>  2    sp1     2 10.621776 11.311097
    #>  3    sp1     3 10.800875 10.988726
    #>  4    sp1     4  8.611108 11.653929
    #>  5    sp1     5  9.285643  8.559195
    #>  6    sp2     6  9.675939 11.947356
    #>  7    sp2     7 10.690643 11.736936
    #>  8    sp2     8 10.250548  0.000000
    #>  9    sp2     9 11.007352  0.000000
    #> 10    sp2    10 10.573235  0.000000
    #> 11    sp3     8  0.000000 10.387483
    #> 12    sp3     9  0.000000 12.280034
    

    如果给定的 igenus 有多个值,这将失败,您必须创建一个更唯一的标识符列。

    【讨论】:

    • @C8H10N4O2 不,这会为您提供不同的 data.frame,其行数与 df (19) 相同,而不是 output 的第 12 行。
    • 谢谢!这很好用。我遇到的一个问题,但能够以低效的方式解决,是Site1Site2 变量成为因素的问题,fill=0 不起作用。所以我在每个变量上使用了 as.numeric 函数并将所有 NA 更改为 0。有没有办法在 tidyr 函数中解决这个问题?
    • 真正最好的方法是避免事先将它们作为因素(read.csv 中的stringsAsFactors = FALSE,如果这是来源)。如果它们是数字因素,请特别小心; as.numeric(factor(2:3)) 将返回 1:2,因为这就是值存储在下面的内容,因此您必须执行 as.numeric(as.character(factor(2:3)))
    猜你喜欢
    • 1970-01-01
    • 2023-03-29
    • 2013-05-01
    • 1970-01-01
    • 2020-01-26
    • 2022-01-26
    • 2021-02-16
    • 1970-01-01
    • 2016-03-12
    相关资源
    最近更新 更多