2017-08-19 9 views
1

Ich versuche, Textdaten in Pandas DataFrame basierend auf bestimmten Tags und Werten in den Feldern einer anderen Spalte zu analysieren und sie in ihren eigenen Spalten zu speichern. Zum Beispiel, wenn ich diesen Datenrahmen, df erstellt:Neue Pandas-Spalten mit Regex-Analyse

df = pd.DataFrame([[1,2],['A: this is a value B: this is the b val C: and here is c.','A: and heres another a. C: and another c']]) 
df = df.T 
df.columns = ['col1','col2'] 


df['tags'] = df['col2'].apply(lambda x: re.findall('(?:\s|)(\w*)(?::)',x)) 
all_tags = [] 

for val in df['tags']: 
    all_tags = all_tags + val 
all_tags = list(set(all_tags)) 
for val in all_tags: 
    df[val] = '' 

df: 
    col1            col2  tags A C B 
0 1 A: this is a value B: this is the b val C: and... [A, B, C]  
1 2   A: and heres another a. C: and another c  [A, C] 

Wie würde ich jeden der neuen „Tag“ Spalten mit ihren Werten von col2 bevölkern, so erhalte ich diese df:

col1            col2   tags \ 
0 1 A: this is a value B: this is the b val C: and... [A, B, C] 
1 2   A: and heres another a. C: and another c  [A, C] 

        A    C     B 
0  this is a value and here is c. this is the b val 
1 and heres another a. and another c 

Antwort

4

Eine weitere Option str.extractall mit regex(?P<key>\w+):(?P<val>[^:]*)(?=\w+:|$):

Die regex den Schlüssel (?P<key>\w+) vor dem Semikolon und Wert nach dem Semikolon fängt (?P<val>[^:]*) als zwei getrennte Säulen key und val, die val passt nicht : Zeichen, bis es das nächste Schlüsselwertpaar erreicht, eingeschränkt durch eine Look-Ahead-Syntax (?=\w+:|$); Dies setzt voraus, der Schlüssel ist, immer ein einziges Wort, das nicht eindeutig anders sein würde:

import re 
pat = re.compile("(?P<key>\w+):(?P<val>[^:]*)(?=\w+:|$)") 

pd.concat([ 
    df, 
    (
     df.col2.str.extractall(pat) 
      .reset_index('match', drop=True) 
      .set_index('key', append=True) 
      .val.unstack('key') 
    ) 
], axis=1).fillna('') 

enter image description here


Wo str.extractall gibt:

df.col2.str.extractall(pat) 

enter image description here

Und Sie dann schwenken das Ergebnis und verketten wi th der ursprüngliche Datenrahmen.

1

hier eine Weg

In [683]: (df.col2.str.findall('[\S]+(?:\s(?!\S+:)\S+)+') 
      .apply(lambda x: pd.Series(dict([v.split(':', 1) for v in x]))) 
     ) 
Out[683]: 
         A     B    C 
0  this is a value this is the b val and here is c. 
1 and heres another a.     NaN and another c 

Sie könnten die Ergebnisse anhängen zurück join

In [690]: df.join(df.col2.str.findall('[\S]+(?:\s(?!\S+:)\S+)+') 
        .apply(lambda x: pd.Series(dict([v.split(':', 1) for v in x])))) 
Out[690]: 
    col1            col2  tags \ 
0 1 A: this is a value B: this is the b val C: and... [A, B, C] 
1 2   A: and heres another a. C: and another c  [A, C] 

         A     B    C 
0  this is a value this is the b val and here is c. 
1 and heres another a.     NaN and another c 
mit

Split Gruppen in Listen

In [684]: df.col2.str.findall('[\S]+(?:\s(?!\S+:)\S+)+') 
Out[684]: 
0 [A: this is a value, B: this is the b val, C: ... 
1   [A: and heres another a., C: and another c] 
Name: col2, dtype: object 

Nun, um Schlüssel-Wert-Paare von Listen:

Infact, könnten Sie df['tags'] mit String-Methode

In [688]: df.col2.str.findall('(?:\s|)(\w*)(?::)') 
Out[688]: 
0 [A, B, C] 
1  [A, C] 
Name: col2, dtype: object 

Einzelheiten erhalten.

In [685]: (df.col2.str.findall('[\S]+(?:\s(?!\S+:)\S+)+') 
      .apply(lambda x: [v.split(':', 1) for v in x])) 
Out[685]: 
0 [[A, this is a value], [B, this is the b val... 
1 [[A, and heres another a.], [C, and another c]] 
Name: col2, dtype: object