【问题标题】:Identify number or character sequence along an R dataframe column沿 R 数据框列识别数字或字符序列
【发布时间】:2019-02-26 12:14:10
【问题描述】:
mydf <- tibble::tribble(
   ~seq, ~flag,
      0,     0,
      0,     0,
      0,     0,
      1,     1,
      1,     1,
      7,     1,
      1,     1,
      3,     1,
      2,     1,
      1,     1,
      1,     1,
      0,     1,
      0,     1,
      0,     0,
      0,     0,
      1,     1,
      1,     1,
      7,     1,
      1,     1,
      3,     1,
      2,     1,
      1,     1,
      1,     1,
      0,     1,
      0,     1,
      0,     0,
      0,     0,
      2,     0
)

我有一个带有序列列的数据框。如何创建二进制标志来标记任何特定的数字序列?我的示例序列是 1、1、7、1、3、2、1、1、0、0。

【问题讨论】:

  • 不是完全重复,但请查看this question
  • 也许把seq列当作一个字符串paste(mydf$seq, collapse = ","),然后用grep?

标签: r dataframe dplyr tidyr zoo


【解决方案1】:
library(zoo)
match_seq <- c(1, 1, 7, 1, 3, 2, 1, 1, 0, 0)
is_start <- rollapply(mydf$seq, length(match_seq), function(x) all(x == match_seq))
inds <- sapply(which(is_start), `+`, seq_along(match_seq) - 1)

mydf$flag2 <- as.numeric(1:nrow(mydf) %in% inds)


#    seq flag flag2
# 1    0    0     0
# 2    0    0     0
# 3    0    0     0
# 4    1    1     1
# 5    1    1     1
# 6    7    1     1
# 7    1    1     1
# 8    3    1     1
# 9    2    1     1
# 10   1    1     1
# 11   1    1     1
# 12   0    1     1
# 13   0    1     1
# 14   0    0     0
# 15   0    0     0
# 16   1    1     1
# 17   1    1     1
# 18   7    1     1
# 19   1    1     1
# 20   3    1     1
# 21   2    1     1
# 22   1    1     1
# 23   1    1     1
# 24   0    1     1
# 25   0    1     1
# 26   0    0     0
# 27   0    0     0
# 28   2    0     0

在没有library(zoo) 的情况下计算is_start 的一种方法是

subseqs <- 
  sapply(seq(0, nrow(mydf) - length(match_seq)), 
         function(i) mydf$seq[i + seq_along(match_seq)])

is_start <- colMeans(subseqs == match_seq) == 1

【讨论】:

  • 干得好!以前没听说过rollapply()
【解决方案2】:

使用tidyverse 的解决方案。

library(tidyverse)

st <- str_c(mydf$seq, collapse = "")

pos <- str_locate_all(st, "1171321100")

index <- map2(pos[[1]][, 1], pos[[1]][, 2], `:`) %>% unlist()


mydf2 <- mydf %>%
  mutate(Result = as.integer(row_number() %in% index))
mydf2
# # A tibble: 28 x 3
#     seq  flag Result
#    <dbl> <dbl>  <int>
#  1     0     0      0 
#  2     0     0      0
#  3     0     0      0
#  4     1     1      1
#  5     1     1      1
#  6     7     1      1
#  7     1     1      1
#  8     3     1      1
#  9     2     1      1
# 10     1     1      1
# # ... with 18 more rows

【讨论】:

  • 假设seq 是个位数的列。
  • @zx8754 好。我的解决方案仅适用于单个数字列。欢迎更高级或通用的。
  • @zx8754 一个想法是使用str_pad 添加前导0 如果同时存在单数或双(或更多)数字,然后应用相同的策略,但这取决于是否OP需要它。如果是这样,我欢迎 OP 发布另一个示例,我会在有时间时更新我的​​帖子。
  • 我想到了与 cmets 中的 collapse = "," 类似的解决方案,因此被评论为“警告”。同意 OP 需要澄清输入。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-06
  • 2020-11-14
  • 2015-07-20
  • 1970-01-01
相关资源
最近更新 更多