Extract word in quotes from string - r

I am using R to extract words from short text pieces. Specifically, I want to extract any word that appear in quotes (") from a string, but not when it appears inside brackets ().
For instance, I would like the "hello" first of the 3 strings, but not the other two:
c('"hello" world', 'hello world', '("hello") world')
Original code attempt
str_extract(x, '(?<=")[^$]+(?<=")')

You may use this regex with nested look arounds in str_extract:
(?<=(?<!\()")[^"]+(?=(?!\))")
RegEx Demo
RegEx Details:
(?<=(?<!\()"): Assert that we have a " before but don't have a ( before "
[^"]+: Match 1+ of any characters that are not "
(?=(?!\))"): Assert that we have a " after but don't have a ) after "
Code:
str_extract(x, '(?<=(?<!\\()")[^"]+(?=(?!\\))")')
or avoid double escaping by using a character class:
str_extract(x, '(?<=(?<![(])")[^"]+(?=(?![)])")')

We can use a regex lookaround
library(stringr)
ifelse(grepl('\\("', str1), NA, str_extract(str1, '(?<=")\\w+'))
#[1] "hello" NA NA
data
str1 <- c("\"hello\" world", "hello world", "(\"hello\") world")

Related

How to throw out spaces and underscores only from the beginning of the string?

I want to ignore the spaces and underscores in the beginning of a string in R.
I can write something like
txt <- gsub("^\\s+", "", txt)
txt <- gsub("^\\_+", "", txt)
But I think there could be an elegant solution
txt <- " 9PM 8-Oct-2014_0.335kwh "
txt <- gsub("^[\\s+|\\_+]", "", txt)
txt
The output should be "9PM 8-Oct-2014_0.335kwh ". But my code gives " 9PM 8-Oct-2014_0.335kwh ".
How can I fix it?
You could bundle the \s and the underscore only in a character class and use quantifier to repeat that 1+ times.
^[\s_]+
Regex demo
For example:
txt <- gsub("^[\\s_]+", "", txt, perl=TRUE)
Or as #Tim Biegeleisen points out in the comment, if only the first occurrence is being replaced you could use sub instead:
txt <- sub("[\\s_]+", "", txt, perl=TRUE)
Or using a POSIX character class
txt <- sub("[[:space:]_]+", "", txt)
More info about perl=TRUE and regular expressions used in R
R demo
The stringr packages offers some task specific functions with helpful names. In your original question you say you would like to remove whitespace and underscores from the start of your string, but in a comment you imply that you also wish to remove the same characters from the end of the same string. To that end, I'll include a few different options.
Given string s <- " \t_blah_ ", which contains whitespace (spaces and tabs) and underscores:
library(stringr)
# Remove whitespace and underscores at the start.
str_remove(s, "[\\s_]+")
# [1] "blah_ "
# Remove whitespace and underscores at the start and end.
str_remove_all(s, "[\\s_]+")
# [1] "blah"
In case you're looking to remove whitespace only – there are, after all, no underscores at the start or end of your example string – there are a couple of stringr functions that will help you keep things simple:
# `str_trim` trims whitespace (\s and \t) from either or both sides.
str_trim(s, side = "left")
# [1] "_blah_ "
str_trim(s, side = "right")
# [1] " \t_blah_"
str_trim(s, side = "both") # This is the default.
# [1] "_blah_"
# `str_squish` reduces repeated whitespace anywhere in string.
s <- " \t_blah blah_ "
str_squish(s)
# "_blah blah_"
The same pattern [\\s_]+ will also work in base R's sub or gsub, with some minor modifications, if that's your jam (see Thefourthbird`s answer).
You can use stringr as:
txt <- " 9PM 8-Oct-2014_0.335kwh "
library(stringr)
str_trim(txt)
[1] "9PM 8-Oct-2014_0.335kwh"
Or the trimws in Base R
trimws(txt)
[1] "9PM 8-Oct-2014_0.335kwh"

A regex to remove all words which contains number in R

I want to write a regex in R to remove all words of a string containing numbers.
For example:
first_text = "a2c if3 clean 001mn10 string asw21"
second_text = "clean string
Try with gsub
trimws(gsub("\\w*[0-9]+\\w*\\s*", "", first_text))
#[1] "clean string"
It is easier to select words with no numbers than to select and delete words with numbers:
> library(stringr)
> str1 <- "a2c if3 clean 001mn10 string asw21"
> paste(unlist(str_extract_all(str1, "(\\b[^\\s\\d]+\\b)")), collapse = " ")
[1] "clean string"
Note:
Backslashes have to be escaped in R to work properly, hence double backslashes
\b is word boundary
\s is white space
\d is digit character
a caret (^) inside square brackets is a negater: find characters that do not match ...
"+" after the character group inside [] means "1 or more" occurrences of those (non white space and non digit) characters
Just another alternative using gsub
trimws(gsub("[^\\s]*[0-9][^\\s]*", "", first_text, perl=T))
#[1] "clean string"
A bit longer than some of the answers but very tractable is to first convert the string to a vector of words, then check word by word if there are any numbers and use standard R subsetting.
first_text_vec <- strsplit(first_text, " ")[[1]]
first_text_vec
[1] "a2c" "if3" "clean" "001mn10" "string" "asw21"
paste(first_text_vec[!grepl("[0-9]", first_text_vec)], collapse = " ")
[1] "clean string"

Put space after a specifc word in a string vector in R

I want to put a space after a specific character in a string vector in R.
Example:
Text <-"<U+00A6>Word"
My goal is to put a space after the ">" to seperate the string in two characters to come to: <U+00A6> Word
I tried with gsub, but I do not have the right idea:
Text = gsub("<*", " ", Text)
But that only puts a space after each character.
Can you advise on that?
You can use this:
sub(">", "> ", Text)
# [1] "<U+0093> Word"
or this (without repeating the >):
sub("(?<=>)", " ", Text, perl = TRUE)
# [1] "<U+0093> Word"
If you just want to extract Word, you can use:
sub(".*>", "", Text)
# [1] "Word"
We can use str_extract to extract the word after the >
library(stringr)
str_extract(Text, "(?<=>)\\w+")
#[1] "Word"
Or another option is strsplit
strsplit(Text, ">")[[1]][2]
#[1] "Word"

Removing punctuation between two words

I have a data frame (df) and I would like to remove punctuation.
However there an issue with dot between 2 words and at the end of one word like this:
test.
test1.test2
I use this to remove the punctuation:
library(tm)
removePunctuation(df)
and the result I take is this:
test
test1test2
but I would like to take this as result:
test
test1 test2
How is it possible to have a space between two words in the removing process?
You can use chartr for single character substitution:
chartr(".", " ", c("test1.test2"))
# [1] "test1 test2"
#akrun suggested trimws to remove the space at the end of your test string:
str <- c("test.", "test1.test2")
trimws(chartr(".", " ", str))
# [1] "test" "test1 test2"
We can use gsub to replace the . with a white space and remove the trailing/leading spaces (if any) with trimws.
trimws(gsub('[.]', ' ', str1))
#[1] "test" "test1 test2"
NOTE: In regex, . by itself means any character. So we should either keep it inside square brackets[.]) or escape it (\\.) or with option fixed=TRUE
trimws(gsub('.', ' ', str1, fixed=TRUE))
data
str1 <- c("test.", "test1.test2")
you can also use strsplit:
a <- "test."
b <- "test1.test2"
do.call(paste, as.list(strsplit(a, "\\.")[[1]]))
[1] "test"
do.call(paste, as.list(strsplit(b, "\\.")[[1]]))
[1] "test1 test2"

Merge Multiple spaces to single space; remove trailing/leading spaces

I want to merge multiple spaces into single space(space could be tab also) and remove trailing/leading spaces.
For example...
string <- "Hi buddy what's up Bro"
to
"Hi buddy what's up bro"
I checked the solution given at Regex to replace multiple spaces with a single space. Note that don't put \t or \n as exact space inside the toy string and feed that as pattern in gsub. I want that in R.
Note that I am unable to put multiple space in toy string.
Thanks
This seems to meet your needs.
string <- " Hi buddy what's up Bro "
library(stringr)
str_replace(gsub("\\s+", " ", str_trim(string)), "B", "b")
# [1] "Hi buddy what's up bro"
Or simply try the squish function from stringr
library(stringr)
string <- " Hi buddy what's up Bro "
str_squish(string)
# [1] "Hi buddy what's up Bro"
Another approach using a single regex:
gsub("(?<=[\\s])\\s*|^\\s+|\\s+$", "", string, perl=TRUE)
Explanation (from)
NODE EXPLANATION
--------------------------------------------------------------------------------
(?<= look behind to see if there is:
--------------------------------------------------------------------------------
[\s] any character of: whitespace (\n, \r,
\t, \f, and " ")
--------------------------------------------------------------------------------
) end of look-behind
--------------------------------------------------------------------------------
\s* whitespace (\n, \r, \t, \f, and " ") (0 or
more times (matching the most amount
possible))
--------------------------------------------------------------------------------
| OR
--------------------------------------------------------------------------------
^ the beginning of the string
--------------------------------------------------------------------------------
\s+ whitespace (\n, \r, \t, \f, and " ") (1 or
more times (matching the most amount
possible))
--------------------------------------------------------------------------------
$ before an optional \n, and the end of the
string
You do not need to import external libraries to perform such a task:
string <- " Hi buddy what's up Bro "
string <- gsub("\\s+", " ", string)
string <- trimws(string)
string
[1] "Hi buddy what's up Bro"
Or, in one line:
string <- trimws(gsub("\\s+", " ", string))
Much cleaner.
The qdapRegex has the rm_white function to handle this:
library(qdapRegex)
rm_white(string)
## [1] "Hi buddy what's up Bro"
You could also try clean from qdap
library(qdap)
library(stringr)
str_trim(clean(string))
#[1] "Hi buddy what's up Bro"
Or as suggested by #Tyler Rinker (using only qdap)
Trim(clean(string))
#[1] "Hi buddy what's up Bro"
For this purpose no need to load any extra libraries as the gsub() of Base r package does the work.
No need to remember those extra libraries.
Remove leading and trailing white spaces with trimws() and replace the extra white spaces using gsub() as mentioned by #Adam Erickson.
`string = " Hi buddy what's up Bro "
trimws(gsub("\\s+", " ", string))`
Here \\s+ matches one or more white spaces and gsub replaces it with single space.
To know what any regular expression is doing, do visit this link as mentioned by #Tyler Rinker.
Just copy and paste the regular expression you want to know what it is doing and this will do the rest.
Another solution using strsplit:
Splitting text into words, and, then, concatenating single words using paste function.
string <- "Hi buddy what's up Bro"
stringsplit <- sapply(strsplit(string, " "), function(x){x[!x ==""]})
paste(stringsplit ,collapse = " ")
For more than one document:
string <- c("Hi buddy what's up Bro"," an example using strsplit ")
stringsplit <- lapply(strsplit(string, " "), function(x){x[!x ==""]})
sapply(stringsplit ,function(d) paste(d,collapse = " "))
This seems to work.
It doesn't eliminate whitespaces at the beginning or the end of the sentence as Rich Scriven's answer
but, it merge multiple whitespices
library("stringr")
string <- "Hi buddy what's up Bro"
str_replace_all(string, "\\s+", " ")
#> str_replace_all(string, "\\s+", " ")
# "Hi buddy what's up Bro"

Resources