r - 如何识别一系列 NA 之前和之后的值
问题描述
我有一组从实验室仪器中获取的 CO2 测量数据。在整个数据收集过程中也偶尔运行标准。模拟数据集如下所示:
tibble(co2=c(464,345,389,831,374,323,486,542,429,624,359,612,738,720,520,454,499,616,952,805,582, 646,566,781,745,615,639,750,780,1119,584,1345,1020,1038,1419,1136),
number.stds=c(3,rep('NA',13),2,rep('NA',20),3),
std.value.1=c(618,rep('NA',13),534,rep('NA',20),546),
std.value.2=c(621,rep('NA',13),564,rep('NA',20),549),
std.value.3=c(625,rep('NA',34),553)) -> data
列co2
是测量数据,number.stds
是测量的标准数量,std.value.1
通过std.value.3
是不同的标准读数。
我想生成一个新列std.value
,它是相邻标准运行的所有标准值的平均值,并分配给在这两个标准运行之间测量的所有样本。
例如,对于第mean(c(618,621,625,534,564))
1 行到第 15 行(含),此新列的值将是 592.4 ( )。对于从 16 到 36 的所有行(包括 16 和 36),它的值将是 549.2 ( mean(c(546,549,553,534,564))
)。
有没有一种简单的方法可以用 dplyr 做到这一点?是否应该以不同的格式收集和组织数据以使这个问题更容易?
解决方案
更新
我最初误解了这个请求。这是一个答案,应该可以为您提供所需的内容。
@qdread 的回答简洁明了。这个更长,但坚持 tidyverse 语法。
library(dplyr)
library(tidyr)
data <- data %>% mutate(grp.start = if_else(!is.na(number.stds), 1, 0),
smpl.grp = cumsum(grp.start),
smpl.grp = if_else(!is.na(number.stds) & row_number() != 1, lag(smpl.grp), smpl.grp)) %>%
select(smpl.grp, everything(), -grp.start)
data.2 <- data %>%
filter(!is.na(number.stds)) %>%
select(smpl.grp, std.value.1:std.value.3) %>%
mutate(smpl.grp = if_else(row_number() == 1, 0, smpl.grp)) %>% #assigns first row a grp # of 0 but keeps its standard values in our dataset, takes care of edge issues going forward.
pivot_longer(std.value.1:std.value.3, names_to = "standard.rep", names_prefix = "std.value.", values_to = "std.values") %>%
select(standard.rep, everything()) %>%
group_by(standard.rep) %>%
arrange(standard.rep, smpl.grp) %>%
mutate(std.values.2 = lag(std.values)) %>%
pivot_longer(std.values:std.values.2, names_to = "std.grps", values_to = "std.values") %>%
group_by(smpl.grp) %>%
summarise(std.n = sum(!is.na(std.values)), std.avg = mean(std.values, na.rm = T)) %>%
left_join(select(data, smpl.grp, co2), .)
data.2
# A tibble: 36 x 4
smpl.grp co2 std.n std.avg
<dbl> <dbl> <int> <dbl>
1 1 464 5 592.
2 1 345 5 592.
3 1 389 5 592.
4 1 831 5 592.
5 1 374 5 592.
6 1 323 5 592.
7 1 486 5 592.
8 1 542 5 592.
9 1 429 5 592.
10 1 624 5 592.
# … with 26 more rows
首先,我为每组样本(“smpl.grp”)分配了一个唯一标识符,您希望将其与不同的标准平均值集进行比较
然后,我们可以删除无关的行并仅使用相关数据:样本组编号和标准值。
下一步会稍微整理数据,pivot_longer()
以便所有标准值都在一个列中。
然后数据按标准代表分组,并按标准代表和样品组 ID 排列。这设置了生成一个附加列,其中包含您希望使用mutate()
和与该组关联的第二组标准值lag()
。
通过再次旋转,您再次确保所有标准值都在一个列中,现在所有标准值都与其所需的样本组 ID 相关联。
然后剩下要做的就是summarise()
按样本组并加入smpl.grp的原始数据集。
DATA(带真NA
s)
tibble(co2=c(464,345,389,831,374,323,486,542,429,624,359,612,738,720,520,454,499,616,952,805,582, 646,566,781,745,615,639,750,780,1119,584,1345,1020,1038,1419,1136),
number.stds=c(3,rep(NA_real_,13),2,rep(NA_real_,20),3),
std.value.1=c(618,rep(NA_real_,13),534,rep(NA_real_,20),546),
std.value.2=c(621,rep(NA_real_,13),564,rep(NA_real_,20),549),
std.value.3=c(625,rep(NA_real_,34),553)) -> data
推荐阅读
- wso2 - WSO2 IS 5.3.0 - 租户的管理员用户可以被锁定/禁用吗?
- asp.net - IIS 上的随机 500 错误
- reporting-services - 在 SSRS 中的查找中格式化字段
- dynamics-crm - CRM 2013 重新排序站点地图功能区中的实体
- .net-core - dotnet core webapi调用.net webapi2
- hash - 将 CRC32 值理解为除法余数
- docker - 在 macOS 上运行时,如何让 GitLab Runner 停止像 Linux 一样运行?
- json - 如何定义模式任意 JSON 对象?
- python-3.x - pandas 基于分布的系列抽样
- android - Android 和 iOS 中的 Nativescript 并发和低延迟音频