[英]How do I gsub the complete time string behind @
(这是我的第一个问题,如果我需要改进它,请告诉我!)
我正在分析一个大型观测数据集。 已指示每次观察的开始和停止时间,以便我能够计算持续时间。 但是有一个注释栏,其中包含有关没有看到动物的“暂停”/“休息”或“看不见”时期的信息。 我想从总持续时间中减去这些时间段。
我的问题是,一列包含几个注释,不仅是暂停(“HH:MM-HH:MM”),还包括某些事件的信息(xy 发生了“@HH:MM”)。
我只想查看格式为 HH:MM-HH:MM 的时间段,并且我想排除所有标记为“@HH:MM”的事件时间。 我设法删除了所有单词,只剩下数字,所以看起来像这样
id <- c("3990", "3989", "3004")
timepoints <- c("@6:19,,7:16-7:23,7:25-7:43,@7:53,", "@6:19,,7:25-7:43,@7:53", "7:30-7:39,7:45-7:48,7:49-7:54")
df <- data.frame(id, timepoints)
尝试了 grep 或 gsub 的几种方法,试图指示要保留哪个,或者忽略哪个,但我失败了。 我得到的最接近的是 r 删除“@HH”但保留“:MM”。 为此我使用
gsub("@([[:digit:]]|[_])*", "", df$timepoints)
,正如在此处发现的与单词类似的问题: 从字符串中删除所有以“@”开头的单词
目的是获得(例如):
ID | 时间点 |
---|---|
3990 | “7:16-7:23、7:25-7:43” |
或者
ID | 时间点 |
---|---|
3990 | “7:16-7:23”、“7:25-7:43” |
如果可能的话,用逗号分隔,或者直接分成不同的列,这样我就可以提取时间并将其从我的总观察时间中减去。
任何帮助将不胜感激!
你可以这样做:
f <- function(x) {
lapply(x, \(s) {
s = strsplit(s,",")[[1]]
s[grepl("^\\d",s)]
})
}
然后将 function 应用于时间点列
library(tidyverse)
mutate(df %>% as_tibble(), timepoints = f(timepoints)) %>%
unnest(timepoints)
Output:
id timepoints
<chr> <chr>
1 3990 7:16-7:23
2 3990 7:25-7:43
3 3989 7:25-7:43
4 3004 7:30-7:39
5 3004 7:45-7:48
6 3004 7:49-7:54
您还可以使用unnest_wider()
将这些作为列; 为此,我会调整我的f()
以包含时间点的名称:
f <- function(x) {
lapply(x, \(s) {
s = strsplit(s,",")[[1]]
s = s[grepl("^\\d",s)]
setNames(s, paste0("tp", 1:length(s)))
})
}
library(tidyverse)
mutate(df %>% as_tibble(), timepoints = f(timepoints)) %>%
unnest_wider(timepoints)
Output:
id tp1 tp2 tp3
<chr> <chr> <chr> <chr>
1 3990 7:16-7:23 7:25-7:43 NA
2 3989 7:25-7:43 NA NA
3 3004 7:30-7:39 7:45-7:48 7:49-7:54
如何匹配您感兴趣的字符串呢?
带base
:
df$new_timepoints <- regmatches(df$timepoints, gregexpr("\\d{1,2}:\\d{2}-\\d{1,2}:\\d{2}", df$timepoints))
Output(带列表栏):
id timepoints new_timepoints
1 3990 @6:19,,7:16-7:23,7:25-7:43,@7:53, 7:16-7:23, 7:25-7:43
2 3989 @6:19,,7:25-7:43,@7:53 7:25-7:43
3 3004 7:30-7:39,7:45-7:48,7:49-7:54 7:30-7:39, 7:45-7:48, 7:49-7:54
使用tidyverse
(为便于计算采用长格式:):
library(stringr)
library(dplyr)
library(tidyr)
df |>
group_by(id) |>
mutate(new_timepoints = str_extract_all(timepoints, "\\d{1,2}:\\d{2}-\\d{1,2}:\\d{2}")) |>
unnest_longer(new_timepoints) |>
ungroup()
Output:
# A tibble: 6 × 3
id timepoints new_timepoints
<chr> <chr> <chr>
1 3990 @6:19,,7:16-7:23,7:25-7:43,@7:53, 7:16-7:23
2 3990 @6:19,,7:16-7:23,7:25-7:43,@7:53, 7:25-7:43
3 3989 @6:19,,7:25-7:43,@7:53 7:25-7:43
4 3004 7:30-7:39,7:45-7:48,7:49-7:54 7:30-7:39
5 3004 7:30-7:39,7:45-7:48,7:49-7:54 7:45-7:48
6 3004 7:30-7:39,7:45-7:48,7:49-7:54 7:49-7:54
1) 用逗号列出拆分,然后用破折号列出 grep 的组件。 不使用任何包。 这给出了一个字符向量列表作为时间点列。
df2 <- df
df2$timepoints <- lapply(strsplit(df$timepoints, ","),
grep, pattern = "-", value = TRUE)
df2
## id timepoints
## 1 3990 7:16-7:23, 7:25-7:43
## 2 3989 7:25-7:43
## 3 3004 7:30-7:39, 7:45-7:48, 7:49-7:54
str(df2)
## 'data.frame': 3 obs. of 2 variables:
## $ id : chr "3990" "3989" "3004"
## $ timepoints:List of 3
## ..$ : chr "7:16-7:23" "7:25-7:43"
## ..$ : chr "7:25-7:43"
## ..$ : chr "7:30-7:39" "7:45-7:48" "7:49-7:54"
2)字符如果你想在每行中添加一个逗号分隔的字符串:
transform(df2, timepoints = sapply(timepoints, paste, collapse = ","))
## id timepoints
## 1 3990 7:16-7:23,7:25-7:43
## 2 3989 7:25-7:43
## 3 3004 7:30-7:39,7:45-7:48,7:49-7:54
3)长格式,或者如果您更喜欢长格式,请使用:
long <- with(df2, stack(setNames(timepoints, id))[2:1])
names(long) <- names(df2)
long
## id timepoints
## 1 3990 7:16-7:23
## 2 3990 7:25-7:43
## 3 3989 7:25-7:43
## 4 3004 7:30-7:39
## 5 3004 7:45-7:48
## 6 3004 7:49-7:54
4)宽格式或宽格式矩阵:
nr <- nrow(long)
L <- transform(long, seq = ave(1:nr, id, FUN = seq_along))
tapply(L$timepoints, L[c("id", "seq")], c)
## seq
## id 1 2 3
## 3990 "7:16-7:23" "7:25-7:43" NA
## 3989 "7:25-7:43" NA NA
## 3004 "7:30-7:39" "7:45-7:48" "7:49-7:54"
使用 package data.table
设置数据
library(data.table)
id <- c("3990", "3989", "3004")
timepoints <- c("@6:19,,7:16-7:23,7:25-7:43,@7:53,", "@6:19,,7:25-7:43,@7:53", "7:30-7:39,7:45-7:48,7:49-7:54")
df <- data.table(id, timepoints)
请注意,我将其保存为data.table
用逗号分割时间点并将值存储在new_time
列中。
df[,new_time:=strsplit(timepoints, ",")]
删除具有@
的字符串值
df[,new_time:=sapply(new_time, function(x) return(x[!grepl("[@]", x)]))]
由于timepoints
列在一行中有多个逗号空字符串( ""
)存在我删除它们
df[,new_time:=sapply(new_time, function(x) return(x[!stringi::stri_isempty(x)]))]
现在new_time
列看起来像这样
df$new_time
[[1]]
[1] "7:16-7:23" "7:25-7:43"
[[2]]
[1] "7:25-7:43"
[[3]]
[1] "7:30-7:39" "7:45-7:48" "7:49-7:54"
如果您想让new_time
列包含整个字符串
df[,new_time:=sapply(new_time, paste, collapse=", ")]
df$new_time
[1] "7:16-7:23, 7:25-7:43" "7:25-7:43" "7:30-7:39, 7:45-7:48, 7:49-7:54"
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.