2017-08-21 14 views
3

Im Grunde bin ich ein Python-Benutzer und benutze die Pandas-Bibliothek auf einer täglichen Basis. Die genannten Capture-Gruppen in Regex sind äußerst nützlich. So ist es zum Beispiel relativ trivial, Vorkommen bestimmter Wörter oder Phrasen zu extrahieren und verkettete Folgen der Ergebnisse in neuen Spalten eines Datenrahmens zu erzeugen. Ein Beispiel, wie dies erreicht werden könnte, wird unten angegeben:Regex benannte Gruppen in R

import numpy as np 
import pandas as pd 
import re 

myDF = pd.DataFrame(['Here is some text', 
        'We all love TEXT', 
        'Where is the TXT or txt textfile', 
        'Words and words', 
        'Just a few works', 
        'See the text', 
        'both words and text'],columns=['origText']) 

print("Original dataframe\n------------------") 
print(myDF) 

# Define regex to find occurrences of 'text' or 'word' as separate named groups 
myRegex = """(?P<textOcc>t[e]?xt)|(?P<wordOcc>word)""" 
myCompiledRegex = re.compile(myRegex,flags=re.I|re.X) 

# Extract all occurrences of 'text' or 'word' 
myMatchesDF = myDF['origText'].str.extractall(myCompiledRegex) 
print("\nDataframe of matches (with multi-index)\n--------------------") 
print(myMatchesDF) 

# Collapse resulting multi-index dataframe into single rows with concatenated fields 
myConcatMatchesDF = myMatchesDF.groupby(level = 0).agg(lambda x: '///'.join(x.fillna(''))) 
myConcatMatchesDF = myConcatMatchesDF.replace(to_replace = "^/+|/+$",value = "",regex = True) # Remove '///' at start and end of strings 
print("\nCollapsed and concatenated matches\n----------------------------------") 
print(myConcatMatchesDF) 

myDF = myDF.join(myConcatMatchesDF) 
print("\nFinal joined dataframe\n----------------------") 
print(myDF) 

Dies erzeugt die folgende Ausgabe:

Original dataframe 
------------------ 
          origText 
0     Here is some text 
1     We all love TEXT 
2 Where is the TXT or txt textfile 
3     Words and words 
4     Just a few works 
5      See the text 
6    both words and text 

Dataframe of matches (with multi-index) 
-------------------- 
     textOcc wordOcc 
    match     
0 0  text  NaN 
1 0  TEXT  NaN 
2 0   TXT  NaN 
    1   txt  NaN 
    2  text  NaN 
3 0   NaN Word 
    1   NaN word 
5 0  text  NaN 
6 0   NaN word 
    1  text  NaN 

Collapsed and concatenated matches 
---------------------------------- 
      textOcc  wordOcc 
0    text    
1    TEXT    
2 TXT///txt///text    
3     Word///word 
5    text    
6    text   word 

Final joined dataframe 
---------------------- 
          origText   textOcc  wordOcc 
0     Here is some text    text    
1     We all love TEXT    TEXT    
2 Where is the TXT or txt textfile TXT///txt///text    
3     Words and words     Word///word 
4     Just a few works    NaN   NaN 
5      See the text    text    
6    both words and text    text   word 

ich jede Stufe gedruckt haben, um zu versuchen es einfach zu machen zu folgen.

Die Frage ist, kann ich etwas Ähnliches in R machen. Ich habe das Internet durchsucht, kann aber nichts finden, was die Verwendung von benannten Gruppen beschreibt (obwohl ich ein R-Newcomer bin und vielleicht danach suche falsche Bibliotheken oder beschreibende Begriffe).

Ich konnte die Elemente identifizieren, die eine oder mehrere Übereinstimmungen enthalten, aber ich kann nicht sehen, wie bestimmte Übereinstimmungen extrahiert werden oder wie die benannten Gruppen verwendet werden. Der Code, den ich bisher habe (den gleichen Datenrahmen und regex wie in dem obigen Beispiel mit Python) ist:

origText = c('Here is some text','We all love TEXT','Where is the TXT or txt textfile','Words and words','Just a few works','See the text','both words and text') 
myDF = data.frame(origText) 
myRegex = "(?P<textOcc>t[e]?xt)|(?P<wordOcc>word)" 
myMatches = grep(myRegex,myDF$origText,perl=TRUE,value=TRUE,ignore.case=TRUE) 
myMatches 
[1] "Here is some text"    "We all love TEXT"     "Where is the TXT or txt textfile" "Words and words"     
[5] "See the text"      "both words and text"    

myMatchesRow = grep(myRegex,myDF$origText,perl=TRUE,value=FALSE,ignore.case=TRUE) 
myMatchesRow 
[1] 1 2 3 4 6 7 

Die Regex scheint zu funktionieren und die richtigen Zeilen sind als die ein Spiel (dh alle außer Reihe identifiziert 5 im obigen Beispiel). Meine Frage ist jedoch, kann ich eine Ausgabe erzeugen, die der von Python ähnlich ist, wo die spezifischen Übereinstimmungen extrahiert und in neuen Spalten im Datenrahmen aufgelistet werden, die mit den Gruppennamen in der Regex benannt sind?

Antwort

3

Base R erfasst die Informationen über die Namen, aber es hat keinen guten Helfer, um sie anhand des Namens zu extrahieren. Ich schreibe einen Wrapper zur Hilfe namens regcapturedmatches. Sie können es mit

myRegex = "(?<textOcc>t[e]?xt)|(?<wordOcc>word)" 
m<-regexpr(myRegex, origText, perl=T, ignore.case=T) 
regcapturedmatches(origText,m) 

Welche

 textOcc wordOcc 
[1,] "text" ""  
[2,] "TEXT" ""  
[3,] "TXT" ""  
[4,] ""  "Word" 
[5,] ""  ""  
[6,] "text" ""  
[7,] ""  "word" 
+0

Absolut perfekt zurück. Vielen Dank für die Freigabe Ihres Codes. Die Verwendung von regexpr() scheint nur die erste Übereinstimmung zurückzugeben, aber die Verwendung von gregexpr() gibt alle Übereinstimmungen zurück. Genau das, wonach ich gesucht habe. – user1718097