簡體   English   中英

將具有不同鍵值對的文本文件轉換為csv文件

[英]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()

注意:

  • 如果你想要快速的性能,我認為你應該避免迭代這些行,無論你使用哪種方法。 如果你在 python 中足夠先進,你可以嘗試使用 Python Multiprocessing。 但是我上面的代碼被剪掉了,避免了所有這些麻煩。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM