间歇行中带有变量的整洁数据

Tidy data with variable in intermittent rows

我的数据记录器每次打开时都会插入一行带有时间戳的数据记录器。时间戳字符串始终是相同的格式,但每个时间戳的读数数量不一致。

如何将时间戳行整理到 time 变量中?

前一个问题很接近,除了我希望额外行中的数据是一个变量,而不是 header(它也有四岁了,我怀疑这些天有更优雅的 tidyverse 解决方案):

library(tidyverse)

df_have <- tribble(
  ~site, ~n,  ~val,
  NA,  "Start 11:22:33", NA,
  "A", "N=1", .1,
  "A", "N=2", .3,
  NA,  "Start 12:33:44", NA,
  "B", "N=1", .2,
  "B", "N=2", .4,
  "B", "N=3", .6
)

df_want <- tribble(
  ~site, ~time, ~n,  ~val,
  "A", "11:22:33", "N=1", .1,
  "A", "11:22:33", "N=2", .3,
  "B", "12:33:44", "N=1", .2,
  "B", "12:33:44", "N=2", .4,
  "B", "12:33:44", "N=3", .6
)

我们可以根据 'n' 中的 'Start' 子字符串创建分组列,通过删除 'Start' 后跟一个或多个 [=32] 创建 'time' =]s(\s+)在'n'的'first'元素中,去掉第一行(slice)和select[=16之后感兴趣的列=]ing

library(dplyr)
library(stringr)
library(tidyr)
df_have %>% 
   group_by(grp = cumsum(str_detect(n, 'Start'))) %>%
   mutate(time = str_remove(first(n), 'Start\s+')) %>%
   slice(-1) %>%
   ungroup %>%
   select(site, time, n, val)

-输出

# A tibble: 5 x 4
#  site  time     n       val
#  <chr> <chr>    <chr> <dbl>
#1 A     11:22:33 N=1     0.1
#2 A     11:22:33 N=2     0.3
#3 B     12:33:44 N=1     0.2
#4 B     12:33:44 N=2     0.4
#5 B     12:33:44 N=3     0.6

或者不分组,我们可以在提取'Start'和space

之后的时间分量后fill
df_have %>%
   mutate(time = str_extract(n, '(?<=Start\s)\S+')) %>%
   fill(time) %>% 
   filter(complete.cases(val))

我们可以使用 separatefill

df_have %>%
  separate("n", c("n","time"), sep=" ") %>% 
  fill(time) %>% 
  drop_na() %>% 
  select(site, time, n, val)

输出:

  site  time     n       val
  <chr> <chr>    <chr> <dbl>
1 A     11:22:33 N=1     0.1
2 A     11:22:33 N=2     0.3
3 B     12:33:44 N=1     0.2
4 B     12:33:44 N=2     0.4
5 B     12:33:44 N=3     0.6

这是另一个解决方案:

library(dplyr)
library(tidyr)

df_have %>%
  mutate(time = replace(sub('Start\s', '', n), !grepl('Start', n), NA)) %>%
  fill(time) %>%
  filter(!grepl('Start', n))

#  site  time     n       val
#  <chr> <chr>    <chr> <dbl>
#1 A     11:22:33 N=1     0.1
#2 A     11:22:33 N=2     0.3
#3 B     12:33:44 N=1     0.2
#4 B     12:33:44 N=2     0.4
#5 B     12:33:44 N=3     0.6