【问题标题】:using multiple data frames and lookup table to perform functions in r使用多个数据帧和查找表在 r 中执行功能
【发布时间】:2019-02-12 03:20:48
【问题描述】:

我是 r 的新手,并且有一组复杂的数据,所以希望我的解释是正确的。我需要使用多个数据框来执行一系列操作。这是一个例子。我有三个数据框。一个是物种名称和对应代码的列表:

>df.sp
    Species Code
    Picea   PI
    Pinus   CA

另一个是包含不同位置 (dir) 物种丰度数据的站点列表。不幸的是,物种的顺序是不同的。

>df.site
Site  dir total  t01 t02 t03 t04
2         Total   PI  CA  AB  T
2     N    9      1   5   na na
2                 AB  ZI PI CA
2     S    5     2   2  1  4
3                 DD  EE AB YT
3     N    6     1   1  5   3
3                 AB YT  EE  DD
3     S     5     4   3  1   1

那我还有一个对应物种的性状数据框:

>df.trait
Species  leaft  rootl
Picea     0.01    1.2
Pinus     0.02    3.5

我想做的一件事是获取每个站点 (df.site$Site) 和每个站点位置的所有物种的每个特征 (df.trait$left 和 df.trait$rootl) 的平均值(df.site$ 站点 N,S)。所以结果将是第一行:

Site dir leaft rootl
2    N   0.015  2.35

我希望这是有道理的。思考如何去做对我来说非常复杂。我曾尝试从this postthis(以及许多其他人)工作,但迷路了。 谢谢您的帮助。真的很感激。

更新:这里是使用 dput 的实际 df.site(减少)示例:

> dput(head(df.site))
structure(list(Site = c(2L, 2L, 2L, 2L, 2L, 2L), dir = c("rep17316", 
"N", "", "S", "", "SE"), total = c("Total", "9", "", 
"10", "", "9"), t01 = c("PI", "4", "CA", "1", "SILLAC", 
"3"), t02 = c("CXBLAN", "3", "ZIZAUR", "4", "OENPIL", "2"), 
    t03 = c("ZIZAPT", "1", "ECHPUR", "2", "ASCSYR", "2")), .Names = c("site", "dir", "total", "t01", "t02", "t03"), row.names = 2:7, class = "data.frame")

【问题讨论】:

  • df.site 在列的类型不一致的情况下看起来非常糟糕(例如,total 列有像 Total 这样的词和像 9 这样的数字,@ 987654333@ 列有像 "T" 这样的词(除非这是一个布尔值 TRUE?),像 "na" 这样的字符串可能应该缺少值 NA,像 4 这样的数字和像 "CA" 这样的常规字符串。第一步将肯定需要使数据成形。您能否与dput 共享该数据框的一个子集,以便它可以复制/粘贴并且我们可以看到所有列类型?(与dput() 共享其他数据也很好...)
  • 如果您需要帮助制作可重现的示例,请参阅this excellent FAQdput(droplevels(df.site[1:10, ])) 应该不错。
  • 然而,一个更好的问题可能是返回到您导入的 df.site 并修复导入过程,而不是尝试修复导致的混乱数据......没有看到样本很难知道这是否会减少工作量。
  • 谢谢。是的,df.site 是一场噩梦,这是问题的一部分。它已正确导入,只是一个难以处理的 csv 文件。我按照建议使用 dput 添加了简化版本。
  • 与 R 无关,但您的示例 Species 列是否更适合命名为 genus? :)

标签: r loops merge lookup-tables


【解决方案1】:

您必须首先将数据整理成更清晰的形式。我假设你上面的dput 的结构在你的df.site 数据帧中是一致的;即行是成对的,第一个指定物种代码,第二个有一个计数(或其他一些收集的数据?)。

df作为你上面dput()的dataframe开始,我先模拟一下其他两个dataframe的数据:

df.sp <- data.frame(Species = paste0("species",1:8),
                    Code = c("ECHPUR", "CXBLAN", "ZIZAPT",
                             "CAMROT", "SILLAC", "OENPIL",
                             "ASCSYR", "ZIZAUR"))
df.sp
#>    Species   Code
#> 1 species1 ECHPUR
#> 2 species2 CXBLAN
#> 3 species3 ZIZAPT
#> 4 species4 CAMROT
#> 5 species5 SILLAC
#> 6 species6 OENPIL
#> 7 species7 ASCSYR
#> 8 species8 ZIZAUR

df.trait <- data.frame(Species = paste0("species",1:8),
                       leaft = round(runif(8, max=.2), 2),
                       rootl = round(runif(8, min=1, max=4),1))

df.trait
#>    Species leaft rootl
#> 1 species1  0.12   2.5
#> 2 species2  0.04   2.6
#> 3 species3  0.12   2.1
#> 4 species4  0.05   1.1
#> 5 species5  0.15   2.5
#> 6 species6  0.15   3.3
#> 7 species7  0.05   3.9
#> 8 species8  0.13   2.1

首先,让我们清理df,方法是移动包含收集数据的第二行,并将这些值移动到一组新的列中:

library(dplyr)

df.clean <- df %>% 
  #for each row, copy the direction and total from the following row
  mutate_at(vars(matches("dir|total")), lead) %>% 
  #create new columns for observed data and fill in values from following row
  mutate_at(vars(matches("t\\d+$")), 
            .funs = funs(n = lead(.))) %>% 
  #filter to rows with species code in t01
  filter(t01 %in% df.sp$Code) %>% 
  #drop "total" column (doesn't make sense after reshape)
  select(-total)

df.clean
#>   site dir    t01    t02    t03 t01_n t02_n t03_n
#> 1    2   N ECHPUR CXBLAN ZIZAPT     4     3     1
#> 2    2   S CAMROT ZIZAUR ECHPUR     1     4     2
#> 3    2  SE SILLAC OENPIL ASCSYR     3     2     2

我们现在有两组对应的列,分别具有物种代码和值。要将数据框重塑为长格式,我们将使用 data.table 包中的melt()。有关如何执行此操作的其他示例,请参阅对 this question 的回复。

library(data.table)

df.clean <- df.clean %>% 
  setDT() %>% #convert to data.table to use data.tabel::melt
  melt(measure.vars = patterns("t\\d+$", "_n$"),
       value.name = c("Code", "Count") ) %>% 
  #drop "variable" column, which isn't needed
  select(-variable)

最后,加入你的三个数据框:

#merge tables together
df.summaries <- df.clean %>% 
  left_join(df.sp) %>% 
  left_join(df.trait)

此时,您应该可以使用group_bysummarise 将您的数据按您感兴趣的任何分组进行汇总。

【讨论】:

  • 哇。感谢您花费这么多时间来帮助我!这真的,真的很有帮助。我一直在努力奋斗的时间比我想承认的试图将其转换为可用格式的时间更长。离我需要做的事情又近了一大步。谢谢,
猜你喜欢
  • 1970-01-01
  • 2020-03-23
  • 2021-12-25
  • 2014-03-27
  • 2022-12-03
  • 2021-07-27
  • 2016-07-24
  • 2021-01-08
  • 1970-01-01
相关资源
最近更新 更多