在R

时间:2017-12-01 11:00:09

标签: r regex dataframe text

我试图根据具体情况删除句子中的单词列表。

我们说我们有这个数据框:

responses <- c("The Himalaya", "The Americans", "A bird", "The Pacific ocean")
questions <- c("The highest mountain in the world","A cold war serie from 2013","A kiwi which is not a fruit", "Widest liquid area on earth")
df <- cbind(questions,responses)

> df
     questions                           responses          
[1,] "The highest mountain in the world" "The Himalaya"     
[2,] "A cold war serie from 2013"        "The Americans"    
[3,] "A kiwi which is not a fruit"       "A bird"           
[4,] "Widest liquid area on earth"       "The Pacific ocean"

以下具体单词列表:

articles <- c("The","A")
geowords <- c("mountain","liquid area")

我想做两件事:

  1. 在与小写字母开头的单词相邻时,中的第一个位置删除文章

  2. 删除回复列中第一个位置的文章时(与以大写字母开头的单词相邻)和IF(地理位置在相应的问题中)

  3. 预期结果应为:

         questions                           responses      
    [1,] "The highest mountain in the world" "Himalaya"     
    [2,] "A cold war serie from 2013"        "The Americans"
    [3,] "A kiwi which is not a fruit"       "bird"         
    [4,] "Widest liquid area on earth"       "Pacific ocean"
    

    我尝试gsub没有成功,因为我对正则表达不熟悉... 我在Stackoverflow中搜索时没有发现类似的问题。如果一个R和正则表达式全明星可以帮助我,我会非常感谢!

4 个答案:

答案 0 :(得分:0)

与您提到的相同,已写为两个逻辑列,ifelse用于验证和gsub

responses <- c("The Himalaya", "The Americans", "A bird", "The Pacific ocean")
questions <- c("The highest mountain in the world","A cold war serie from 2013","A kiwi which is not a fruit", "Widest liquid area on earth")
df <- data.frame(cbind(questions,responses), stringsAsFactors = F)

df

articles <- c("The ","A ")
geowords <- c("mountain","liquid area")


df$f_caps <- unlist(lapply(df$responses, function(x) {grepl('[A-Z]',str_split(str_split(x,' ', simplify = T)[2],'',simplify = T)[1])}))


df$geoword_flag <- grepl(paste(geowords,collapse='|'),df[,1])


df$new_responses <- ifelse((df$f_caps & df$geoword_flag) | !df$f_caps, 
                     {gsub(paste(articles,collapse='|'),'', df$responses )  },
                     df$responses)

df$new_responses


> df$new_responses
[1] "Himalaya"      "The Americans" "bird"          "Pacific ocean"

答案 1 :(得分:0)

为了好玩,这是一个整齐的解决方案:

# Define articles
articles <- c("The", "A")

# Make it a regex alternation
art_or <- paste0(articles, collapse = "|")

# Before a lowercase / uppercase
art_upper <- paste0("(?:", art_or, ")", "\\s", "(?=[A-Z])")
art_lower <- paste0("(?:", art_or, ")", "\\s", "(?=[a-z])")

# Work on df
df4 <-
  df %>%
  as.tibble() %>%
  mutate(responses =
        if_else(str_detect(questions, geowords),
                str_replace_all(string = responses,
                                pattern = regex(art_upper),
                                replacement = ""),
                str_replace_all(string = responses,
                                pattern = regex(art_lower),
                                replacement = "")
                )
        )

编辑:没有“第一个字”正则表达式,灵感来自@Calvin Taylor

System.setProperty("https.proxyHost", "myProxy");
System.setProperty("https.proxyPort", "80");

答案 2 :(得分:0)

我今天自学了一些R.我用一个函数来得到相同的结果。

#!/usr/bin/env Rscript

# References
# https://stackoverflow.com/questions/1699046/for-each-row-in-an-r-dataframe

responses <- c("The Himalaya", "The Americans", "A bird", "The Pacific ocean")
questions <- c("The highest mountain in the world","A cold war serie from 2013","A kiwi which is not a fruit", "Widest liquid area on earth")
df <- cbind(questions,responses)

articles <- c("The","A")
geowords <- c("mountain","liquid area")

common_pattern <- paste( "(?:", paste(articles, "", collapse = "|"), ")", sep = "")
pattern1 <- paste(common_pattern, "([a-z])", sep = "")
pattern2 <- paste(common_pattern, "([A-Z])", sep = "")
geo_pattern <- paste(geowords, collapse = "|")

f <- function (x){ 
  q <- x[1]
  r <- x[2]
  a1 <- gsub (pattern1, "\\1", r)
  if ( grepl(geo_pattern, q)){
    a1 <- gsub (pattern2, "\\1", a1)
  }
  x[1] <- q
  x[2] <- a1
}

apply (df, 1, f)

运行;

Rscript stacko.R
[1] "Himalaya"      "The Americans" "bird"          "Pacific ocean"

答案 3 :(得分:0)

您可以选择使用简单的正则表达式,greplgsub,如下所示:

df <- data.frame(cbind(questions,responses), stringsAsFactors = F) #Changing to data frame, since cbind gives a matrix, stringsAsFactors will prevent to not change the columns to factors
regx <- paste0(geowords, collapse="|") # The "or" condition between the geowords 
articlegrep <- paste0(articles, collapse="|") # The "or" condition between the articles
df$responses <- ifelse(grepl(regx, df$questions)|grepl(paste0("(",articlegrep,")","\\s[a-z]"), df$responses), 
       gsub("\\w+ (.*)","\\1",df$responses),df$responses) #The if condition for which replacement has to happen

> print(df)
                          questions     responses
#1 The highest mountain in the world      Himalaya
#2        A cold war serie from 2013 The Americans
#3       A kiwi which is not a fruit          bird
#4       Widest liquid area on earth Pacific ocean