簡體   English   中英

正則表達式讀取 Python 中的 txt 文件

[英]regex on reading a txt file in Python

我有一個包含用於分類目的數據的 txt。 第一列是 class,即 0 或 1,其他四列包含 class 的特征。 然而,這些功能前面有數字,即 1:用於功能 1、2:用於功能 2 等。我嘗試在 numpy 拆分中使用正則表達式,但我失敗了。 我怎樣才能只取我需要的列? 以下是帶有數據的txt。

1 1:2.617300e+01 2:5.886700e+01 3:-1.894697e-01 4:1.251225e+02
1 1:5.707397e+01 2:2.214040e+02 3:8.607959e-02 4:1.229114e+02
1 1:1.725900e+01 2:1.734360e+02 3:-1.298053e-01 4:1.250318e+02
1 1:2.177940e+01 2:1.249531e+02 3:1.538853e-01 4:1.527150e+02
1 1:9.133997e+01 2:2.935699e+02 3:1.423918e-01 4:1.605402e+02
1 1:5.537500e+01 2:1.792220e+02 3:1.654953e-01 4:1.112273e+02
1 1:2.956200e+01 2:1.913570e+02 3:9.901439e-02 4:1.034076e+02
1 1:1.451200e+02 2:2.088600e+02 3:-1.760859e-01 4:1.542257e+02
1 1:3.849699e+01 2:4.146600e+01 3:-1.886419e-01 4:1.239661e+02
1 1:2.927699e+01 2:1.072510e+02 3:1.149632e-01 4:1.077885e+02
1 1:2.886700e+01 2:1.090240e+02 3:-1.239433e-01 4:9.799130e+01
1 1:2.401300e+01 2:7.602000e+01 3:2.850990e-01 4:9.891692e+01
1 1:2.837900e+01 2:1.452160e+02 3:3.870011e-01 4:1.549975e+02
1 1:2.238140e+01 2:8.242810e+01 3:-2.814865e-01 4:8.998764e+01
1 1:1.232100e+02 2:4.561600e+02 3:-1.518468e-01 4:1.432996e+02
1 1:2.008405e+01 2:1.774510e+02 3:2.578101e-01 4:9.253101e+01
1 1:3.285699e+01 2:1.826750e+02 3:2.204406e-01 4:9.457175e+01
1 1:0.000000e+00 2:1.154780e+02 3:1.504970e-01 4:1.096315e+02
1 1:3.954504e+01 2:2.374420e+02 3:1.089429e-01 4:1.376333e+02
1 1:1.067980e+02 2:3.237560e+02 3:-1.509505e-01 4:1.754021e+02
1 1:3.408200e+01 2:1.198280e+02 3:2.200156e-01 4:1.383639e+02
1 1:0.000000e+00 2:8.671080e+01 3:4.201880e-01 4:1.298851e+02
1 1:4.865997e+01 2:3.071500e+02 3:1.756066e-01 4:1.640174e+02
1 1:2.341090e+01 2:8.347140e+01 3:1.766868e-01 4:9.803250e+01
1 1:1.222390e+02 2:4.357930e+02 3:-1.812907e-01 4:1.687663e+02
1 1:1.624560e+01 2:4.830620e+01 3:5.508614e-01 4:2.632639e+01
1 1:4.389899e+01 2:2.421300e+02 3:2.006008e-01 4:1.331948e+02
1 1:6.143698e+01 2:2.338500e+02 3:2.758731e-01 4:1.612433e+02
1 1:5.952499e+01 2:2.176700e+02 3:-8.601014e-02 4:1.170831e+02
1 1:2.915850e+01 2:1.259875e+02 3:1.910455e-01 4:1.279927e+02
1 1:5.059702e+01 2:2.430620e+02 3:1.863443e-01 4:1.352273e+02
1 1:6.024097e+01 2:1.977340e+02 3:-1.319924e-01 4:1.320220e+02
1 1:2.620490e+01 2:6.270790e+01 3:-1.402450e-01 4:1.135866e+02
1 1:2.847198e+01 2:1.483760e+02 3:-1.868249e-01 4:1.672337e+02
1 1:2.707990e+01 2:7.770390e+01 3:-2.509235e-01 4:9.798032e+01
1 1:2.068600e+01 2:8.446800e+01 3:1.761782e-01 4:1.199423e+02
1 1:1.962450e+01 2:4.923090e+01 3:4.302725e-01 4:9.361318e+01
1 1:4.961401e+01 2:3.234850e+02 3:-1.963741e-01 4:1.622486e+02
1 1:7.982401e+01 2:2.017540e+02 3:-1.412161e-01 4:1.310716e+02
1 1:6.696402e+01 2:2.214030e+02 3:-1.187778e-01 4:1.416626e+02
1 1:5.842999e+01 2:1.348610e+02 3:2.876077e-01 4:1.286684e+02
1 1:6.982007e+01 2:3.693401e+02 3:-1.539849e-01 4:1.511659e+02
1 1:1.902200e+01 2:2.210120e+02 3:1.689450e-01 4:1.368066e+02
1 1:4.582898e+01 2:2.215950e+02 3:2.419124e-01 4:1.627100e+02

您希望解析這樣的一行:

1 1:2.617300e+01 2:5.886700e+01 3:-1.894697e-01 4:1.251225e+02

您的解析器使用以下慣用語讀取輸入:

for line in input_file:

首先從特征中區分 class label。

    label, *raw_features = line.split()
    label = int(label)

現在只剩下從每個功能中去除無用的 N: 前綴了。

    features = [float(feat.split(':')[1])
                for feat in raw_features]

當然,你可以用正則表達式解決這個問題。 但這聽起來不是最簡單的解決方案,在這種情況下。

我很無聊:-),所以想為你寫一個片段。 見下文,這是一種臟文本處理並將其加載到 dataframe。

lines = open("predictions.txt", "r").readlines()
column_lines = [
    [fline[0]] + [feat[1] for feat in sorted([tuple(feature.split(":")) for feature in fline[1:]], key=lambda f: f[0])]
    for fline in [line.split(" ") for line in lines]
]

import pandas as pd
table = pd.DataFrame(column_lines, columns = ["Class", "Feature1","Feature2","Feature3","Feature4"])

除了這個,你還可以考慮將文件轉換為csv,使用類似的文本處理,然后直接使用它們創建一個dataframe,這樣你就不需要每次都運行這個代碼了!

我希望這是有幫助的。

我討厭 pandas 但試試這三行:

import pandas as pd

# Use pandas read_csv; sep is interpreted as a regex
x=pd.read_csv('file.txt',sep='[: ]').to_numpy()

# Now select the required columns
output=x[:,(2,4,6,8)]
print(output)

"""
array([[ 5.707397e+01,  2.214040e+02,  8.607959e-02,  1.229114e+02],
       [ 1.725900e+01,  1.734360e+02, -1.298053e-01,  1.250318e+02],
       [ 2.177940e+01,  1.249531e+02,  1.538853e-01,  1.527150e+02],
       [ 9.133997e+01,  2.935699e+02,  1.423918e-01,  1.605402e+02],
       [ 5.537500e+01,  1.792220e+02,  1.654953e-01,  1.112273e+02],
       [ 2.956200e+01,  1.913570e+02,  9.901439e-02,  1.034076e+02]])
"""

文檔: https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html

您還可以查看如何在將文件讀入 numpy 數組或類似文件時使用正則表達式作為分隔符 function

我獨立地重新發現了下面的解決方案,但這個答案通過sep遵循相同的策略:

https://stackoverflow.com/a/51195469/1021819

如果你想使用正則表達式只提取你的列,你可以在每一行上使用這個正則表達式:

import re

line = '1 1:1.067980e+02 2:3.237560e+02 3:-1.509505e-01 4:1.754021e+02'
reg = re.compile(r'(-*\d+\.\d+e[+|-]\d+)')
# Your columns:
reg.findall(line)
>>> ['1.067980e+02', '3.237560e+02', '-1.509505e-01', '1.754021e+02']
# Assuming you also want numbers of those values:
list(map(float, reg.findall(line)))
>>> [106.798, 323.756, -0.1509505, 175.4021]

什么是: (-*\d+\.\d+e[+|-]\d+)第一個括號用於創建組。 在組內第一個-*是可選的減號。 此后至少有 1 個數字,但可以有超過 1 個\d+ 該數字確實有一個帶小數的小數點,因此\.\d+ 然后有一個帶有 + 或 - e[+|-]后跟數字\d+的指數。

暫無
暫無

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

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