Итак, у меня есть файл, который импортирует большие объемы данных из системы машинного зрения. Он сохраняет данные в текстовом файле и содержит около 4000 строк текста, по 1 строке на результат. Я добавлю 1 из этих строк ниже в качестве примера.

02.11.1970; 11:56:44.000;ID;002914;Light Check;254;Ширина трубки1;38,7;Ширина трубки2;39,2;Ширина трубки3;39,9;Ширина трубки4;40,9;Ширина трубки5;41,2;Фиксированный ряд;175,20;Фиксированный столбец;211,23; Ширина стойки;0,00;Размер капли;0;Левый угол;0,00;Правый угол;17,90;Темная капля;0;Результат;0;Глобальная ул;14;Флажок инструмента;31;Номер поддона; 108;

Итак, что я хочу сделать, так это извлечь для каждой строки один из параметров вместе с его значением. Существует разделитель ; между каждым пространством, которое усложняет мне жизнь.

Итак, если бы я, например, хотел выбрать Light Check, я бы получил результаты Light Check для каждой строки, которая в данном случае равна 254. Может ли кто-нибудь предложить некоторые функции, которые я мог бы использовать, которые могли бы помочь мне в этом?

0
KieranF 4 Фев 2022 в 11:10
1
Можно ли использовать Pandas для решения вашей проблемы?
 – 
Corralien
4 Фев 2022 в 11:22
2
Может быть, вы не знаете, но если один ответ решает вашу проблему, вы должны принять его. meta.stackexchange.com/a/5235
 – 
Corralien
4 Фев 2022 в 11:53
Я никогда не знал этого, спасибо
 – 
KieranF
4 Фев 2022 в 11:55

3 ответа

Лучший ответ

Я предлагаю использовать регулярное выражение (модуль re здесь), пусть содержимое file.txt будет

11/02/1970; 11:56:44.000;ID;002914;Light Check;254;Tube Width1;38.7;Tube Width2;39.2;Tube Width3;39.9;Tube Width4;40.9;Tube Width5;41.2;Fixt Row;175.20;Fixt Col;211.23;Post Width;0.00;Blob Size;0;Left Angle;0.00;Right Angle;17.90;Dark Blob;0;Result;0;Global St;14;Tool Flag;31;Pallet No; 108;

Тогда

import re
with open("file.txt","r") as f:
    for line in f:
        print(re.search(r"Light Check;([0-9]+)",line).group(1))

Выход

254

Объяснение: я перебираю следующие строки (for line in f, поэтому нет необходимости загружать весь файл в память), затем в каждой строке я нахожу 1 или более (+) цифр ([0-9] ) после Light Check;. Обратите внимание, что цифры находятся внутри ( и ), которые являются группой захвата (первой и единственной), к которой я обращаюсь с помощью group(1). Отказ от ответственности: это решение предполагает, что Light Check;, за которым следует 1 или более цифр, присутствует в каждой строке file.txt.

1
Daweo 4 Фев 2022 в 11:31
Это работает очень хорошо, спасибо. Только дополнительный вопрос. Можно ли использовать это регулярное выражение, но вместо простой проверки оно будет принимать входные данные и извлекать данные на основе введенного параметра? Поэтому, если я наберу Light Check, я получу результаты легкой проверки.
 – 
KieranF
4 Фев 2022 в 11:37
1
Да, просто убедитесь, что вы вводите пользовательский ввод в re.escape , прежде чем использовать его как часть шаблона, чтобы предотвратить нежелательное поведение, если он содержит символ специального значения, и замените [0-9] на [.0-9], если вам нужно поддерживать значения с плавающей запятой.
 – 
Daweo
4 Фев 2022 в 11:41
Итак, я новичок в этом, и регулярные выражения для меня довольно продвинуты. Это то, что я пробовал. импортировать повторно с помощью open("file.txt","r") как f: для строки в f: s = input("Введите параметр:") re.escape(s) print(re.search(s, r"( [0-9]+)",строка).группа(1)) @Daweo
 – 
KieranF
4 Фев 2022 в 12:18
1
Вы уверены, что хотите снова запрашивать у пользователя каждую строку? Если не input должен быть вне цикла for, вам нужно объединить, чтобы получить один str для использования в качестве шаблона, попробуйте print(re.search(re.escape(s) + r"([0-9]+)",line).group(1)) (обратите внимание, что это предполагает, что ; будет частью пользовательского ввода)
 – 
Daweo
4 Фев 2022 в 13:04
Хорошо вау, так намного лучше. Я помещаю ввод вне цикла for. Спасибо за всю вашу помощь, я очень ценю это.
 – 
KieranF
4 Фев 2022 в 13:18

Чтобы разделить эту строку на словарь, я бы сделал:

s = "11/02/1970; 11:56:44.000;ID;002914;Light Check;254;Tube Width1;38.7;Tube Width2;39.2;Tube Width3;39.9;Tube Width4;40.9;Tube Width5;41.2;Fixt Row;175.20;Fixt Col;211.23;Post Width;0.00;Blob Size;0;Left Angle;0.00;Right Angle;17.90;Dark Blob;0;Result;0;Global St;14;Tool Flag;31;Pallet No; 108;"

s = s.split(";")
data = {key: val for key, val in zip(s[::2], s[1::2])}

Что возвращается

data
{'11/02/1970': ' 11:56:44.000', 'ID': '002914', 'Light Check': '254', 'Tube Width1': '38.7', 'Tube Width2': '39.2', 'Tube Width3': '39.9', 'Tube Width4': '40.9', 'Tube Width5': '41.2', 'Fixt Row': '175.20', 'Fixt Col': '211.23', 'Post Width': '0.00', 'Blob Size': '0', 'Left Angle': '0.00', 'Right Angle': '17.90', 'Dark Blob': '0', 'Result': '0', 'Global St': '14', 'Tool Flag': '31', 'Pallet No': ' 108'}

Затем вы можете сделать

data['Light Check']

Получить

'254'
2
Tom McLean 4 Фев 2022 в 15:25
1
Это именно то, что я искал, спасибо. Я попробую.
 – 
KieranF
4 Фев 2022 в 11:26

Преобразуйте свою структуру данных в список dict:

import csv
from datetime import datetime

with open('data.txt') as fp:
    reader = csv.reader(fp, delimiter=';')
    data = []
    for row in reader:
        row = row[:-1]
        d = {'dt': datetime.strptime(row[0] + row[1], '%d/%m/%Y %H:%M:%S.%f'),
             'id': row[3]}

        keys = row[4::2]
        vals = map(float, row[5::2])
        d.update(dict(zip(keys, vals)))
        data.append(d)

Выход:

>>> data
[{'dt': datetime.datetime(1970, 2, 11, 11, 56, 44),
  'id': '002914',
  'Light Check': 254.0,
  'Tube Width1': 38.7,
  'Tube Width2': 39.2,
  'Tube Width3': 39.9,
  'Tube Width4': 40.9,
  'Tube Width5': 41.2,
  'Fixt Row': 175.2,
  'Fixt Col': 211.23,
  'Post Width': 0.0,
  'Blob Size': 0.0,
  'Left Angle': 0.0,
  'Right Angle': 17.9,
  'Dark Blob': 0.0,
  'Result': 0.0,
  'Global St': 14.0,
  'Tool Flag': 31.0,
  'Pallet No': 108.0}]

Поиск с помощью Python:

out = [rec for rec in data if rec.get('Light Check') == 254]

Поиск с пандами:

df = pd.DataFrame(data)
out = df[df['Light Check'] == 254]
1
Corralien 4 Фев 2022 в 11:35