Saya mencoba mengurai data teks di Pandas DataFrame berdasarkan tag dan nilai tertentu di bidang kolom lain dan menyimpannya di kolomnya sendiri. Misalnya, jika saya membuat kerangka data ini, df:

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]

Bagaimana saya mengisi setiap kolom "tag" baru dengan nilainya dari col2 jadi saya mendapatkan df ini:

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 
2
this_is_david 19 Agustus 2017, 19:44

2 jawaban

Jawaban Terbaik

Opsi lain menggunakan str.extractall dengan regex (?P<key>\w+):(?P<val>[^:]*)(?=\w+:|$):

regex menangkap kunci (?P<key>\w+) sebelum titik koma dan nilai setelah titik koma (?P<val>[^:]*) sebagai dua kolom terpisah key dan val, val akan mencocokkan karakter non : hingga mencapai pasangan nilai kunci berikutnya yang dibatasi oleh sintaks lihat ke depan (?=\w+:|$); Ini mengasumsikan kuncinya selalu satu kata yang akan menjadi ambigu jika tidak:

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


Di mana str.extractall memberikan:

df.col2.str.extractall(pat)

enter image description here

Dan kemudian Anda memutar hasilnya dan menggabungkan dengan bingkai data asli.

4
Psidom 19 Agustus 2017, 17:04

Inilah salah satu caranya

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

Anda dapat menambahkan kembali hasil menggunakan 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

Faktanya, Anda bisa mendapatkan df['tags'] menggunakan metode string

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

Detail:

Pisahkan grup ke dalam daftar

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

Sekarang, untuk pasangan kunci dan nilai daftar.

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
2
Zero 19 Agustus 2017, 16:59