【问题标题】:specific function through list under certain conditions (for loop and/or function)在特定条件下通过列表的特定函数(for循环和/或函数)
【发布时间】:2021-02-24 20:34:52
【问题描述】:

我有 20 年测量值 (14600x6) 的数据集,需要根据 $name$trophic 获得 $tu 的几何平均值。最初,我将我的 df 拆分为三个 df,然后我做了如下操作:

基于拆分df的旧代码!!!

trophic_pp<- df_pp %>% select(sites, name, tu_pp)%>%
  group_by(name) %>%
  mutate(row = row_number()) %>%
  pivot_wider(names_from = name, values_from = tu_pp) %>%
  replace(is.na(.), 0)%>%
  select(-row)
trophic_dc<- ...... same
trophic_pt<- ...... same

然后

trophic_pp<- trophic_pp%>%
  mutate(sum_pp = rowSums(across(where(is.numeric))))
trophic_dc<- ...... same
trophic_pt<- ...... same

然后

trophic_pp_sites <- select("trophic_pp", "sites", "sum_pp") %>%
  group_by(sites) %>%
  summarise(gmean = gmean(sum_pp)) %>%
  add_column(trophic = "pp", .before = "gmean")
trophic_dc<- ...... same
trophic_pt<- ...... same

然后我合并并简化为最终情节

all_trophic <- Reduce(function(x, y) merge(x, y, all=TRUE), list(trophic_pp,
                                                                 trophic_dc,
                                                                 trophic_pt)) %>%
  mutate(type = case_when(
    startsWith(sites, "R") ~ "river",
    startsWith(sites, "T") ~ "tributary"
    ))

如您所见,这是一个冗长且重复的代码。

我将数据重新排列为只有一个 df 而不是三个,str 现在看起来像这样:

tibble [14,100 x 6] (S3: tbl_df/tbl/data.frame)
     $ name             : Factor w/ 6 levels "Al","As","Cu",..: 1 1 1 1 1 1 1 1 1 1 ...
     $ cas              : chr [1:14100] "7429-90-5" "7429-90-5" "7429-90-5" "7429-90-5" ...
     $ sites            : chr [1:14100] "R1" "R1" "R1" "R5" ...
     $ conc             : num [1:14100] 12.12 12.12 12.12 2.06 2.06 ...
     $ trophic          : chr [1:14100] "tu_pp" "tu_pc" "tu_sc" "tu_pp" ...
     $ tu               : num [1:14100] 12.41 4.83 7.22 2.11 0.82 ...

每个$name 都有自己的$cas、9 个$sites,每个$tu 是根据$conc 和三个不同的$trophics 计算的。因此,$tu 是每一行中唯一变化的变量。

我正在努力计算几何平均值。我尝试如下:

定义几何平均函数

gmean <- function(x, na.rm=TRUE){
  gmean = exp(mean(log(x)))
}

根据 $trophic 创建了一个列表

trophic_list <- split(df, df$trophic)

并通过列表运行 lapply 函数

for (i in seq_along(trophic_list)) {
  
  trophic_list[[i]] <- within(trophic_list[[i]], {

  gmean <- lapply(trophic_list[tu], FUN: gmean
    
  })
}

抱歉,解释太长了,非常感谢您的帮助

【问题讨论】:

  • tidyverse 解决方案是一种选择吗?
  • 欢迎任何减少我的代码重复的建议
  • 也许我遗漏了一些东西,因为您没有发布示例数据,但似乎您可以在 group 语句中添加更多变量,因为您按多个变量分组,然后如果您真的希望它们以这种方式设置,请使用 transpose/pivot_wider 重命名。
  • 您的原始代码是trophic_pp&lt;- df_pp %&gt;% select(sites, name, tu_pp)%&gt;% group_by(name) %&gt;%。您不能只使用合并的数据框并执行trophic_merged&lt;- df_merged %&gt;% select(sites, name, tu_pp)%&gt;% group_by(name,trophic) %&gt;% 之类的操作吗?在分组语句中添加trophic 列就像运行代码 3 种方式。
  • 从不拆分似乎更有意义,pivot_wider 并从 trophic 中获取数据以重命名度量。取决于接下来发生的事情,这可能是必要的,也可能不是必要的。

标签: r function for-loop


【解决方案1】:

如果您可以使用整洁的诗句,这是实现您想要的一种方法:

library(tidyverse)

#use cars to play with
cars <- mpg

#function for geometric mean
#from here https://stackoverflow.com/questions/2602583/geometric-mean-is-there-a-built-in
geo_mean = function(x, na.rm=TRUE){
    exp(sum(log(x[x > 0]), na.rm=na.rm) / length(x))
}

#calculate geometric mean per manufacture and year
#in your case group by trophic/name
geo_mean_summary <- cars %>%
    group_by(manufacturer, year) %>%
    summarize(geoMean_City = geo_mean(cty),
              geoMean_HWY = geo_mean(hwy))

如果适用于您的情况,请注意有关如何处理负值(0 或缺失)的帖子 cmets。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-22
    • 1970-01-01
    • 1970-01-01
    • 2021-02-11
    • 1970-01-01
    相关资源
    最近更新 更多