【问题标题】:Split a column based on round bracket occurrence根据出现的圆括号拆分列
【发布时间】:2020-04-12 11:19:18
【问题描述】:

我的数据可以从这里下载

tuesdata <- tidytuesdayR::tt_load(2020, week = 4)
spotify <- tuesdata$spotify_songs

我希望 track_name 里面没有任何 () 和文本。

预期输出:如果我的曲目名称是 RITMO(Bad Boys For Life),我希望它只有 RITMO。

我们可以将 () 中的部分,即 Bad Boys For Life 在这种情况下放入一个单独的专栏专长中。我正在尝试使用以下方法,看到 10-20 SO 问题,但无法弄清楚。

spotify %>%
  extract(., track_name, into = c("track_name2", "feat"), "(\\.+)\\s*(.*)",remove = F) 

我知道我的正则表达式有问题,但不确定如何获得预期的输出

为 spotify 添加 dput

structure(list(track_id = c("6f807x0ima9a1j3VPbc7VN", "0r7CVbZTWZgbTCYdfa2P31", 
"1z1Hg7Vb0AhHDiEmnDE79l", "75FpbthrwQmzHlBJLuGdC7", "1e8PAfcKUYoKkxPhrHqw4x", 
"7fvUMiyapMsRRxr07cU8Ef"), track_name = c("I Don't Care (with Justin Bieber) - Loud Luxury Remix", 
"Memories - Dillon Francis Remix", "All the Time - Don Diablo Remix", 
"Call You Mine - Keanu Silva Remix", "Someone You Loved - Future Humans Remix", 
"Beautiful People (feat. Khalid) - Jack Wins Remix"), track_artist = c("Ed Sheeran", 
"Maroon 5", "Zara Larsson", "The Chainsmokers", "Lewis Capaldi", 
"Ed Sheeran"), track_popularity = c(66, 67, 70, 60, 69, 67), 
    track_album_id = c("2oCs0DGTsRO98Gh5ZSl2Cx", "63rPSO264uRjW1X5E6cWv6", 
    "1HoSmj2eLcsrR0vE9gThr4", "1nqYsOef1yKKuGOVchbsk6", "7m7vv9wlQ4i0LFuJiE2zsQ", 
    "2yiy9cd2QktrNvWC2EUi0k"), track_album_name = c("I Don't Care (with Justin Bieber) [Loud Luxury Remix]", 
    "Memories (Dillon Francis Remix)", "All the Time (Don Diablo Remix)", 
    "Call You Mine - The Remixes", "Someone You Loved (Future Humans Remix)", 
    "Beautiful People (feat. Khalid) [Jack Wins Remix]"), track_album_release_date = c("2019-06-14", 
    "2019-12-13", "2019-07-05", "2019-07-19", "2019-03-05", "2019-07-11"
    ), playlist_name = c("Pop Remix", "Pop Remix", "Pop Remix", 
    "Pop Remix", "Pop Remix", "Pop Remix"), playlist_id = c("37i9dQZF1DXcZDD7cfEKhW", 
    "37i9dQZF1DXcZDD7cfEKhW", "37i9dQZF1DXcZDD7cfEKhW", "37i9dQZF1DXcZDD7cfEKhW", 
    "37i9dQZF1DXcZDD7cfEKhW", "37i9dQZF1DXcZDD7cfEKhW"), playlist_genre = c("pop", 
    "pop", "pop", "pop", "pop", "pop"), playlist_subgenre = c("dance pop", 
    "dance pop", "dance pop", "dance pop", "dance pop", "dance pop"
    ), danceability = c(0.748, 0.726, 0.675, 0.718, 0.65, 0.675
    ), energy = c(0.916, 0.815, 0.931, 0.93, 0.833, 0.919), key = c(6, 
    11, 1, 7, 1, 8), loudness = c(-2.634, -4.969, -3.432, -3.778, 
    -4.672, -5.385), mode = c(1, 1, 0, 1, 1, 1), speechiness = c(0.0583, 
    0.0373, 0.0742, 0.102, 0.0359, 0.127), acousticness = c(0.102, 
    0.0724, 0.0794, 0.0287, 0.0803, 0.0799), instrumentalness = c(0, 
    0.00421, 2.33e-05, 9.43e-06, 0, 0), liveness = c(0.0653, 
    0.357, 0.11, 0.204, 0.0833, 0.143), valence = c(0.518, 0.693, 
    0.613, 0.277, 0.725, 0.585), tempo = c(122.036, 99.972, 124.008, 
    121.956, 123.976, 124.982), duration_ms = c(194754, 162600, 
    176616, 169093, 189052, 163049)), class = c("tbl_df", "tbl", 
"data.frame"), row.names = c(NA, -6L))

【问题讨论】:

  • 这有点不清楚。试试"^(.*?)(?:\\(([^()]*)\\).*)?$"I Don't Care (with Justin Bieber) - Loud Luxury RemixBeautiful People (feat. Khalid) - Jack Wins Remix 怎么办?
  • 那么,"^(.*?)(?:\\(([^()]*)\\).*)?$" 是否按预期工作?
  • 不是每一列都有括号中的文本 (()) ,在这种情况下你想返回什么。你能显示这 6 行的预期输出吗?可能,删除此问题不需要的其他列。
  • @RonakShah,对于这种情况,我只想返回显示的字符串。基本上我只是想消除一切如果有这个'('符号开始

标签: r regex tidyverse dplyr


【解决方案1】:

样本数据:

    library(dplyr)
    (d <- tribble( ~track_name,
               "RITMO (Bad Boys For Life)",
               "I Don't Care (with Justin Bieber) - Loud Luxury Remix",
               "Vaibhav. Thank you."
))

使用正则表达式模式提取数据。

    library(stringr)

    d %>% mutate(
          is_paran_avail = str_detect(track_name, "\\(") & str_detect(track_name, "\\)"),
          name = if_else(is_paran_avail,
                         str_extract(track_name, pattern = ".+(?=\\()"),
                         track_name)
                )

输出:

奖励: Cheat sheet 模式总是有用的。

另外,对于括号内的文本,您可以使用 str_locate()str_sub() 希望对你有帮助!!!

【讨论】:

  • 这是错误的,因为对于没有括号的情况。它给了NA。例如:我有一个你的 track_name 形状。因为这给了我 NA 的名字
  • @VaibhavSingh 如果我们没有括号,您还没有澄清您需要什么。但是,您可以在 mutate func 中使用 if_else 条件来避免 NA 并根据您的意愿更新 NA。
  • 我同意,如果您添加了这一行,只需添加该答案即可。我很感谢你,只是在这里添加它,以便你可以提高你的贡献,因为你是一个新的贡献者。做得好 ! spotify %>% mutate(name = str_extract(track_name, pattern =".+(?=\()"), name=ifelse(is.na(name),track_name,name))
  • @VaibhavSingh 更新了我的答案以纳入您的需求。谢谢。
  • 谢谢,我知道你在那里做了什么:)
【解决方案2】:

以下代码仅删除括号内的文本,假设 df 有如下两列(track_num 和 track_name)

样本数据:

df

df[,1]

df[,2]

colnames(df)

提取所需的模式:

  • 删除任何带括号的文本(包括括号):

    lapply(df[,2],function(x) str_replace(x, "\(.*\)", ""))

  • 删除括号开头的所有文本:

    lapply(df[,2],function(x) stri_split(x,fixed = "(")[[1]][1])

【讨论】:

    猜你喜欢
    • 2020-07-03
    • 1970-01-01
    • 1970-01-01
    • 2017-09-03
    • 2021-05-14
    • 1970-01-01
    • 1970-01-01
    • 2019-01-23
    • 2022-01-10
    相关资源
    最近更新 更多