Reputation: 2317
I want to substring out a phrase that's in the middle of a string in R. The string is a field in a data frame. It data frame looks something like this:
Common.name price description
Animal 1 $50 Field Collected\nRoughly 2-3 Inches In Length\nVibrant Red Coloration\nWill Do Fine In Groups\nFeeding On Various Vegetation & Fruits\nSizes Range From 1-2.5 Feet In Total Length\nField Collected\nSizes Vary From Juvenile ...
Animal 2 $40 Captive Bred\nApproximately 10-12 Inches In Length\nBeautiful Hybrid to Add To Your Collection\nInsane Patterning And Beautiful Vibrant Colors\nMales And Females...
... ... ... ...
Animal 500 $29 Field Collected Beauties\nMales And Females Available\nApproximate Length: no bigger than a penny\nAmazingly Friendly! Make Great Pets!\nOnly Reach About 9 Inches At Most!\nFeeding On Vitamin Dusted Greens And ...
I want to extract the length and units in each description as new fields. For Animal 1 it would be 2-3 in one field and inches in another field. For Animal 500 the length would be "no bigger than a penny" and the unit field would be NA.
How can I do this in R?
Upvotes: 0
Views: 468
Reputation: 14990
This Regex will do the following:
Animal
followed by a numberlength
somewhere in the field234
or a range of numbers 3-342
:
The Regex
^(?<Animal>Animal\s[0-9]+)\s+\S+\s+(?:(?:(?!\\n|$).)*\\n)*?(?=(?:(?!\\n).)*Length)(?:(?:(?!\\n).)*?(?<Length>[0-9]+\s*(?:-\s*[0-9]+)?)\s+(?<UnitOfMeasure>\S+)|(?:(?!\\n).)*?Length:\s*(?<Length>(?:(?!\\n).)*))?
Notes
\n
strings in your source text were literally \n
or if they represented return characters. So this regex is constructed to assume they are literally a \
character followed by a n
character. If you meant these characters to represent a new line character, then change all the \\n
to \n
in the regexLive example
https://regex101.com/r/nL1fW1/2
Sample input text
Common.name price description
Animal 1 $50 Field Collected\nRoughly 2-3 Inches In Length\nVibrant Red Coloration\nWill Do Fine In Groups\nFeeding On Various Vegetation & Fruits\nSizes Range From 1-2.5 Feet In Total Length\nField Collected\nSizes Vary From Juvenile ...
Animal 2 $40 Captive Bred\nApproximately 10-12 Inches In Length\nBeautiful Hybrid to Add To Your Collection\nInsane Patterning And Beautiful Vibrant Colors\nMales And Females...
Animal 3 $40 Captive Bred\nApproximately 10 Inches In Length\nBeautiful Hybrid to Add To Your Collection\nInsane Patterning And Beautiful Vibrant Colors\nMales And Females...
... ... ... ...
Animal 500 $29 Field Collected Beauties\nMales And Females Available\nApproximate Length: no bigger than a penny\nAmazingly Friendly! Make Great Pets!\nOnly Reach About 9 Inches At Most!\nFeeding On Vitamin Dusted Greens And ...
Sample Matches
[0][0] = Animal 1 $50 Field Collected\nRoughly 2-3 Inches
[0][Animal] = Animal 1
[0][Length] = 2-3
[0][UnitOfMeasure] = Inches
[1][0] = Animal 2 $40 Captive Bred\nApproximately 10-12 Inches
[1][Animal] = Animal 2
[1][Length] = 10-12
[1][UnitOfMeasure] = Inches
[2][0] = Animal 3 $40 Captive Bred\nApproximately 10 Inches
[2][Animal] = Animal 3
[2][Length] = 10
[2][UnitOfMeasure] = Inches
[3][0] = Animal 500 $29 Field Collected Beauties\nMales And Females Available\nApproximate Length: no bigger than a penny
[3][Animal] = Animal 500
[3][UnitOfMeasure] =
[3][Length] = no bigger than a penny
This was copied from the explanation field in the live link above.
^ assert position at start of a line
(?<Animal>Animal\s[0-9]+) Named capturing group Animal
Animal matches the characters Animal literally (case sensitive)
\s match any white space character [\r\n\t\f ]
[0-9]+ match a single character present in the list below
Quantifier: + Between one and unlimited times, as many times as possible, giving back as needed [greedy]
0-9 a single character in the range between 0 and 9
\s+ match any white space character [\r\n\t\f ]
Quantifier: + Between one and unlimited times, as many times as possible, giving back as needed [greedy]
\S+ match any non-white space character [^\r\n\t\f ]
Quantifier: + Between one and unlimited times, as many times as possible, giving back as needed [greedy]
\s+ match any white space character [\r\n\t\f ]
Quantifier: + Between one and unlimited times, as many times as possible, giving back as needed [greedy]
(?:(?:(?!\\n|$).)*\\n)*? Non-capturing group
Quantifier: *? Between zero and unlimited times, as few times as possible, expanding as needed [lazy]
(?:(?!\\n|$).)* Non-capturing group
Quantifier: * Between zero and unlimited times, as many times as possible, giving back as needed [greedy]
(?!\\n|$) Negative Lookahead - Assert that it is impossible to match the regex below
1st Alternative: \\n
\\ matches the character \ literally
n matches the character n literally (case sensitive)
2nd Alternative: $
$ assert position at end of a line
. matches any character (except newline)
\\ matches the character \ literally
n matches the character n literally (case sensitive)
(?=(?:(?!\\n).)*Length) Positive Lookahead - Assert that the regex below can be matched
(?:(?!\\n).)* Non-capturing group
Quantifier: * Between zero and unlimited times, as many times as possible, giving back as needed [greedy]
(?!\\n) Negative Lookahead - Assert that it is impossible to match the regex below
\\ matches the character \ literally
n matches the character n literally (case sensitive)
. matches any character (except newline)
Length matches the characters Length literally (case sensitive)
(?:(?:(?!\\n).)*?(?<Length>[0-9]+\s*(?:-\s*[0-9]+))\s+(?<UnitOfMeasure>\S+)|(?:(?!\\n).)*?Length:\s*(?<Length>(?:(?!\\n).)*))? Non-capturing group
Quantifier: ? Between zero and one time, as many times as possible, giving back as needed [greedy]
1st Alternative: (?:(?!\\n).)*?(?<Length>[0-9]+\s*(?:-\s*[0-9]+))\s+(?<UnitOfMeasure>\S+)
(?:(?!\\n).)*? Non-capturing group
Quantifier: *? Between zero and unlimited times, as few times as possible, expanding as needed [lazy]
(?!\\n) Negative Lookahead - Assert that it is impossible to match the regex below
\\ matches the character \ literally
n matches the character n literally (case sensitive)
. matches any character (except newline)
(?<Length>[0-9]+\s*(?:-\s*[0-9]+)?) Named capturing group Length
[0-9]+ match a single character present in the list below
Quantifier: + Between one and unlimited times, as many times as possible, giving back as needed [greedy]
0-9 a single character in the range between 0 and 9
\s* match any white space character [\r\n\t\f ]
Quantifier: * Between zero and unlimited times, as many times as possible, giving back as needed [greedy]
(?:-\s*[0-9]+)? Non-capturing group
- matches the character - literally
\s* match any white space character [\r\n\t\f ]
Quantifier: * Between zero and unlimited times, as many times as possible, giving back as needed [greedy]
[0-9]+ match a single character present in the list below
Quantifier: + Between one and unlimited times, as many times as possible, giving back as needed [greedy]
0-9 a single character in the range between 0 and 9
\s+ match any white space character [\r\n\t\f ]
Quantifier: + Between one and unlimited times, as many times as possible, giving back as needed [greedy]
(?<UnitOfMeasure>\S+) Named capturing group UnitOfMeasure
\S+ match any non-white space character [^\r\n\t\f ]
Quantifier: + Between one and unlimited times, as many times as possible, giving back as needed [greedy]
2nd Alternative: (?:(?!\\n).)*?Length:\s*(?<Length>(?:(?!\\n).)*)
(?:(?!\\n).)*? Non-capturing group
Quantifier: *? Between zero and unlimited times, as few times as possible, expanding as needed [lazy]
(?!\\n) Negative Lookahead - Assert that it is impossible to match the regex below
\\ matches the character \ literally
n matches the character n literally (case sensitive)
. matches any character (except newline)
Length: matches the characters Length: literally (case sensitive)
\s* match any white space character [\r\n\t\f ]
Quantifier: * Between zero and unlimited times, as many times as possible, giving back as needed [greedy]
(?<Length>(?:(?!\\n).)*) Named capturing group Length
(?:(?!\\n).)* Non-capturing group
Quantifier: * Between zero and unlimited times, as many times as possible, giving back as needed [greedy]
(?!\\n) Negative Lookahead - Assert that it is impossible to match the regex below
\\ matches the character \ literally
n matches the character n literally (case sensitive)
. matches any character (except newline)
m modifier: multi-line. Causes ^ and $ to match the begin/end of each line (not only begin/end of string)
g modifier: global. All matches (don't return on first match)
J modifier: Allow duplicate subpattern names
Upvotes: 1