间歇行中带有变量的整洁数据
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))
我们可以使用 separate
、fill
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
我的数据记录器每次打开时都会插入一行带有时间戳的数据记录器。时间戳字符串始终是相同的格式,但每个时间戳的读数数量不一致。
如何将时间戳行整理到 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))
我们可以使用 separate
、fill
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