[英]Convert a text file with different key value pairs to a csv file
我有一個文本文件,如下面的示例所示,我想將其轉換為 csv 文件(當前使用 Pandas)。
挑戰在於我事先不知道鍵是什么(列標題)以及它們的順序。
最終的列順序並不重要。
示例文件:
name: john| dob: 10-06-1960| address: 4853 Radio Park Drive
name: jane| dob: 07-10-1973| address: 1537 Timbercrest Road| mobile: 706-289-6746
name: liam| dob: 12-08-1986| address: 4853 498 Fairmont Avenue| telephone number: 706-687-5021
name: chris| dob: 09-12-1965| address: 485 Green Avenue| state: California| Telephone Number: 510-855-5213
所需的 output:
Name | dob | address | mobile | telephone number | state |
-----+------------+--------------------------+--------------+------------------+------------+
john | 10-06-1960 | 4853 Radio Park Drive | | | |
jane | 07-10-1973 | 1537 Timbercrest Road | 706-289-6746 | | |
liam | 12-08-1986 | 4853 498 Fairmont Avenue | | 706-687-5021 | |
chris| 09-12-1965 | 485 Green Avenue | | 510-855-5213 | California |
我的代碼:
import pandas as pd
df = pd.DataFrame()
file = open('D:\sample.log', 'r')
lines = file.readlines()
for line in lines:
pairs = line.split('|')
my_dict = {}
for pair in pairs:
key = pair.split(': ')[0].strip()
value = pair.split(': ')[1].strip()
my_dict[key] = value
df.append(my_dict, ignore_index=True)
這種附加方式非常慢。 我怎樣才能讓它更快。
或者是否有更好的解決方案(例如通過 json 字符串)?
長話短說:
pd.DataFrame.from_records(
dict(field.split(': ') for field in line.split('|'))
for line in lines
)
長版
假設您已經將數據拆分成行,那么您需要將它們處理成記錄,例如:
{' address': '4853 Radio Park Drive', ' dob': '10-06-1960', 'name': 'john'}
每行需要拆分成字段:
>>> line = 'name: john| dob: 10-06-1960| address: 4853 Radio Park Drive'
>>> line.split('|')
['name: john', ' dob: 10-06-1960', ' address: 4853 Radio Park Drive']
然后需要將每個字段拆分為列名和值本身:
>>> field = 'name: John'
>>> field.split(': ')
['name', 'john']
對行中的每個字段執行此操作后,您最終會得到以下列表:
>>> [field.split(': ') for field in line.split('|')]
[['name', 'john'],
[' dob', '10-06-1960'],
[' address', '4853 Radio Park Drive']]
使用此列表初始化的字典會從答案的開頭獲取記錄。
由於你有很多行,你需要生成很多記錄,但最好是懶惰地生成這些記錄,換句話說,使用生成器:
>>> (dict(field.split(': ') for field in line.split('|')) for line in s.split('\n'))
<generator object <genexpr> at 0x7f0d06bf8dd0>
生成器不會為您生成完整的記錄列表,而是在您遍歷它時一次給您一個。 這樣您就可以開始形成您的 dataframe 而無需等待所有記錄都被處理。
Python 中有一種稱為生成器理解的特殊語法,可讓您定義要作為參數傳遞給函數和構造函數的生成器。
將它們放在一起,我們使用適當的構造函數( from_records
) 和上面定義的生成器構造一個 dataframe :
pd.DataFrame.from_records(
dict(field.split(': ') for field in line.split('|'))
for line in lines
)
這會產生以下 output:
name dob address mobile telephone number state Telephone Number
0 john 10-06-1960 4853 Radio Park Drive NaN NaN NaN NaN
1 jane 07-10-1973 1537 Timbercrest Road 706-289-6746 NaN NaN NaN
2 liam 12-08-1986 4853 498 Fairmont Avenue NaN 706-687-5021 NaN NaN
3 chris 09-12-1965 485 Green Avenue NaN NaN California 510-855-5213
作為獎勵,您也可以通過懶惰地閱讀文件來進一步加快速度。 定義一個用於讀取行的自定義生成器:
def lines(path):
with open(path) as file:
while line := file.readline():
yield line.rstrip()
請注意,這僅適用於 Python 3.8+。 否則,您需要這樣做,而不是使用海象運算符:
def lines(path):
with open(path) as file:
while True:
line = file.readline()
if line:
yield line.rstrip()
else:
return
我認為這是完成此任務的最快方法之一,因為它利用 pandas 庫的內置多處理(用 c/c++ 編寫)比遍歷行快得多。
首先將整個文本讀入一個變量。 然后,
import pandas as pd
data = '''name: john| dob: 10-06-1960| address: 4853 Radio Park Drive
name: jane| dob: 07-10-1973| address: 1537 Timbercrest Road| mobile: 706-289-6746
name: liam| dob: 12-08-1986| address: 4853 498 Fairmont Avenue| telephone number: 706-687-5021
name: chris| dob: 09-12-1965| address: 485 Green Avenue| state: California| Telephone Number: 510-855-5213'''
def get_dict(line_elems):
line_dict = {}
for elem in line_elems:
k, v = elem.split(':')
line_dict[k]=v
return line_dict
df = pd.DataFrame({'lines':data.split('\n')})
df['line_list'] = df['lines'].apply(lambda x:x.split('|'))
df['line_dict'] = df['line_list'].apply(get_dict)
dict_list = df['line_dict'].tolist()
final_df = pd.DataFrame.from_dict(dict_list)
final_df
如果你願意,我可以解釋代碼,但讓我知道它與其他代碼相比的性能。
要從文件中讀取整個文本,您可以使用
with open('my_text_file',mode='r') as file:
data= file.read()
注意:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.