2017-02-12 84 views
3

我有這樣的一個格式的文本文件:熊貓:在結構化非表格文本解析值

k1[a-token] 
v1 
v2 
k2[a-token] 
v1' 
k3[a-token] 
v1" 
v2" 
v3" 

什麼是讀取這些數據轉換成這種形式的數據框最pandorable方式:

 A  B 
0  k1  v1 
1  k1  v2 
2  k2  v1' 
3  k3  v1" 
4  k3  v2" 
5  k3  v3" 

那不涉及手動循環?或者是否有任何其他庫允許我只輸入一些正則表達式來指定我的文本文件的結構並以上述表格形式輸出數據?

+0

目前還不清楚您的格式是什麼。你在每個組的開頭是否在方括號中有一些標記,或者你的'[a-token]'是你在SO上放置的標記,以指示每個組的開始? – DSM

+0

耶的意思是說有一個模式表示鍵值的字符串結束。 – ShS

回答

3

設置
借款從@jezrael

import pandas as pd 
from pandas.compat import StringIO 

temp=u""" 
k1[a-token] 
v1 
v2 
k2[a-token] 
v1' 
k3[a-token] 
v1" 
v2" 
v3" 
""" 
#after testing replace 'StringIO(temp)' to 'filename.csv' 
df = pd.read_csv(StringIO(temp), sep="|", names=['B']) 
print (df) 

  • str.extract用正則表達式指定向前看
  • 使用duplicated,以確定我們要保持行參數。

df = df.B.str.extract('(?P<A>.*(?=\[a-token\]))?(?P<B>.*)', expand=True).ffill() 
df[df.duplicated(subset=['A'])].reset_index(drop=True) 

    A B 
0 k1 v1 
1 k1 v2 
2 k2 v1' 
3 k3 v1" 
4 k3 v2" 
5 k3 v3" 
1

您可以使用read_csv一些分離這是不是在數據像|¥:與extract值與[a-token]並與刪除行上次使用boolean indexing與面具由duplicated

import pandas as pd 
from pandas.compat import StringIO 

temp=u""" 
k1[a-token] 
v1 
v2 
k2[a-token] 
v1' 
k3[a-token] 
v1" 
v2" 
v3" 
""" 
#after testing replace 'StringIO(temp)' to 'filename.csv' 
df = pd.read_csv(StringIO(temp), sep="|", names=['B']) 
print (df) 
      B 
0 k1[a-token] 
1   v1 
2   v2 
3 k2[a-token] 
4   v1' 
5 k3[a-token] 
6   v1" 
7   v2" 
8   v3" 

然後insert新列Akeys in values列:

df.insert(0, 'A', df['B'].str.extract('(.*)\[a-token\]', expand=False).ffill()) 
df = df[df['A'].duplicated()].reset_index(drop=True) 
print (df) 
    A B 
0 k1 v1 
1 k1 v2 
2 k2 v1' 
3 k3 v1" 
4 k3 v2" 
5 k3 v3" 

但是如果文件已經複製keys

print (df) 
       B 
0 k1[a-token] 
1   v1 
2   v2 
3 k2[a-token] 
4   v1' 
5 k3[a-token] 
6   v1" 
7   v2" 
8   v3" 
9 k2[a-token] 
10   v1' 

df.insert(0, 'A', df['B'].str.extract('(.*)\[a-token\]', expand=False).ffill()) 
df = df[df['A'].duplicated()].reset_index(drop=True) 
print (df) 
    A   B 
0 k1   v1 
1 k1   v2 
2 k2   v1' 
3 k3   v1" 
4 k3   v2" 
5 k3   v3" 
6 k2 k2[a-token] 
7 k2   v1' 

然後就是必要的改變mask

df.insert(0, 'A', df['B'].str.extract('(.*)\[a-token\]', expand=False).ffill()) 
df = df[~df['B'].str.contains('\[a-token]')].reset_index(drop=True) 
print (df) 
    A B 
0 k1 v1 
1 k1 v2 
2 k2 v1' 
3 k3 v1" 
4 k3 v2" 
5 k3 v3" 
6 k2 v1' 
0

有了您的文件爲 'TEMP.TXT' ......

df = pd.read_csv('temp.txt', 
       header=None, 
       delim_whitespace=True, 
       names=['data']) 

bins = df.data.str.endswith('[a-token]') 

idx_bins = df[bins][:] 
idx_bins.data = idx_bins.data.str.rstrip(to_strip='[a-token]') 
idx_vals = df[~bins][:] 

a = pd.DataFrame(idx_bins.index.values, columns=['a']) 
b = pd.DataFrame(idx_vals.index.values, columns=['b']) 

merge_df = pd.merge_asof(b, a, left_on='b', right_on='a') 
new_df = pd.DataFrame({'A': idx_bins.data.loc[list(merge_df.a)].values, 
         'B': idx_vals.data.values}) 
+0

整個過程並沒有在代碼中出現任何可見的循環! :) – ShS

+0

對不起@ShS,我沒有正確地讀你的問題。在merge_asof替換循環後,這看起來如何? – b2002