【问题标题】:Split a column in R with inconstant data format在 R 中拆分数据格式不固定的列
【发布时间】:2020-07-31 18:32:31
【问题描述】:

我有一个包含 17 列的 R 数据框。一列包含我将用于与其他数据框合并的唯一标识符。但是,此列中的某些行包含额外的数据,导致无法合并。这是我正在查看的不同类型数据的子集。

M2017013708-MN-M02199-180405
M201701492756-MN-M05144-180419
M2016019446_S3_L001
M2016019762

-MN 之后的所有数据都被认为是需要删除的额外数据。我的目标是在没有额外数据的情况下向数据框添加一个新列。它看起来像这样:

M2017013708
M201701492756
M2016019446_S3_L001
M2016019762

我尝试在 -MN 处拆分数据,这会创建一个列表,然后使用 ldply 将其制成数据框。但是,这会导致错误,因为拆分会导致多个长度的列表,因为并非所有行都有 -MN。

split_my_data <- strsplit(my_data$sample_name, '-MN')
df <- ldply(split_my_data)

我尝试使用带有 sqldf 的 case 和正则表达式。但是,我得到一个没有这样的函数 REGEXP 的错误。

任何帮助将不胜感激。

【问题讨论】:

  • 也许你可以使用gsub("-MN.*", "", my_data$sample_name)
  • 谢谢。效果很好。

标签: r dataframe


【解决方案1】:

或者您可以使用 Look Beind Regex (?

尝试此方法
df <- data.frame(OBS = 1:4, 
                 CODE = c("M2017013708-MN-M02199-180405",
                             "M201701492756-MN-M05144-180419",
                             "M2016019446_S3_L001",
                             "M2016019762"))
df2 <- df %>% 
  mutate(CODE2 = str_replace_all(CODE, regex("(?<=)-MN.*"), ""))
# OBS                           CODE               CODE2
# 1   1   M2017013708-MN-M02199-180405         M2017013708
# 2   2 M201701492756-MN-M05144-180419       M201701492756
# 3   3            M2016019446_S3_L001 M2016019446_S3_L001
# 4   4                    M2016019762         M2016019762

【讨论】:

  • 花式。这是关于正则表达式的非常有用的信息。我以前没有使用过 Look behind Regex,但它对未来的开发非常有用。谢谢。
  • 不客气。谢谢你的好话。我相信还有其他很好的方法可以解决这个问题。
【解决方案2】:

一个简单整洁的解决方案也可以是:

library(dplyr)
library(stringr)

data <- tibble(dirty = c('M2017013708-MN-M02199-180405',
                         'M201701492756-MN-M05144-180419',
                         'M2016019446_S3_L001',
                         'M2016019762'))

data %>%
  mutate(clean = str_remove(dirty, pattern = '-MN.*'))

# A tibble: 4 x 2
  dirty                          clean              
  <chr>                          <chr>              
1 M2017013708-MN-M02199-180405   M2017013708        
2 M201701492756-MN-M05144-180419 M201701492756      
3 M2016019446_S3_L001            M2016019446_S3_L001
4 M2016019762                    M2016019762 

【讨论】:

    【解决方案3】:

    SQLite

    关于 SQLite,正则表达式只有在构建 SQLite 时打开正则表达式支持时才可用,但 RSQLite 没有这样做,因此它不可用。

    您可以做的是将-MN- 附加到每个字符串的末尾以确保始终至少出现一次,然后使用instr 搜索它并使用substr 将子字符串带到该点:

    library(sqldf)
    sqldf("select V1, substr(V1, 1, instr(V1 || '-MN-', '-MN-') - 1) as V2 from DF")
    

    给予:

                                  V1                  V2
    1   M2017013708-MN-M02199-180405         M2017013708
    2 M201701492756-MN-M05144-180419       M201701492756
    3            M2016019446_S3_L001 M2016019446_S3_L001
    4                    M2016019762         M2016019762
    

    H2

    如果我们将 H2 后端用于 sqldf 而不是 SQLite,那么我们可以使用正则表达式。 RH2 包包括 R 驱动程序和 H2 本身,如果加载了它,sqldf 将假定您想使用它而不是 SQLite。 RH2 和 sqldf 的加载顺序无关紧要。

    library(RH2)
    library(sqldf)
    
    sqldf("select V1, regexp_replace(V1, '-MN-.*', '') as V2 from DF")
    

    注意

    可重现形式的输入是:

    DF <- data.frame(V1 = c("M2017013708-MN-M02199-180405",
                            "M201701492756-MN-M05144-180419",
                            "M2016019446_S3_L001",
                            "M2016019762"))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-05
      • 1970-01-01
      • 1970-01-01
      • 2016-09-13
      • 1970-01-01
      相关资源
      最近更新 更多