У меня есть текстовый файл с некоторыми строками, сдвинутыми на одну вкладку, что означает, что они являются подкатегорией основной строки. Мне нужно пометить каждую строку уникальной меткой, обозначающей, к какой «группе» или категории они принадлежат, чтобы провести статистический анализ по каждой категории.

Я не слишком уверен, как автоматизировать это в Python, так как в файле тысячи строк. Я не могу преобразовать файл в csv без предварительного смещения по всем отступам строк, что, очевидно, потеряло бы способность определять, к какой категории относится каждая строка.

EDIT :
Вот снимок экрана с примером текстового файла, который показывает то, о чем я говорю визуально.

Первые 3 строки будут иметь метку группы «1», следующие 2 строки будут иметь метку «2», а последние 2 строки будут иметь метки «3» и «4» соответственно.

2
yeepo 2 Июл 2019 в 00:10

3 ответа

Лучший ответ

Вы можете использовать numpy genfromtext и генератор, чтобы добавить новое поле, если вы хотите построить фрейм данных.

def add_group(fd):
    """generator that prepends each line with a group field (returns byte strings)"""
    digit = re.compile(r'^\d')
    line = next(fd)                     # process header line
    yield('group,'+line).encode()
    group=0
    for line in fd:
        if digit.match(line):           # increment group when first char is a digit
            group += 1
        yield "{},{}".format(group, line).encode()

df = pd.DataFrame(np.genfromtxt(add_group(open('file.txt')), delimiter=',', names=True,
                  autostrip=True, dtype=None)

Если вы хотите только создать CSV, это еще проще:

with open('file.txt') as fd, open('file.csv', 'w') as fdout):
    digit = re.compile(r'^\d')
    fdout.write('group,'+next(fd))     # process header line
    group = 0
    for line in fd:
        if digit.match(line):           # increment group when first char is a digit
            group += 1
        fdout.write("{},{}".format(group, line).encode())
0
Serge Ballesta 2 Июл 2019 в 06:58

Это не лучший способ сделать это, но он должен работать. Прежде всего вам нужно получить все данные из файла. Давайте просто откроем файл и прочитаем все данные построчно в строку под названием data:

with open("your_text_file.txt", "r") as f:
    data = f.read().split('\n')

Чтобы смоделировать ваш файл, я сделал вид, что все данные уже хранятся в переменной данных:

data = """ratio, weight, flags, initialTime, finalTime
15,    0.44,    3,    300500,    400000
    42,    0.31,   2,   900432,   100304
22,    1.31,   3,   200432,   100304
    52,    0.11,   4,   922432,   111304 """
group = 0
data = data.split('\n')
#insert name group in firts line of your data
data[0] = f"group, {data[0]}"
for count,items in enumerate(data[1:]):
    #if line do not start with tab increment group number by 1
    if not items.startswith("    "):
        group += 1
    #insert first raw as group
    items = f"{group}, {items}"
    #deleta all ugly tabs
    items = ' '.join(items.split())
    #rewrite dataline with new beatiful string
    data[count+1] = items
#now create csv file with beautiful data
with open("new_file.csv", "w") as f:
    for items in data:
        f.write(f"{items}\n")

Итак, мои первые данные выглядят так:

ratio, weight, flags, initialTime, finalTime
15,    0.44,    3,    300500,    400000
    42,    0.31,   2,   900432,   100304
22,    1.31,   3,   200432,   100304
    52,    0.11,   4,   922432,   111304 

И после запуска скрипта вот так:

group, ratio, weight, flags, initialTime, finalTime
1, 15, 0.44, 3, 300500, 400000
1, 42, 0.31, 2, 900432, 100304
2, 22, 1.31, 3, 200432, 100304
2, 52, 0.11, 4, 922432, 111304

Надеюсь, это то, что вам нужно

0
Mike Mint 1 Июл 2019 в 23:25

IIUC, здесь относительно простой подход с использованием Pandas и itertools.chain:

import pandas as pd
import numpy as np
import io, re, itertools

data = '''
ratio,  weight, flags,  initialTime,    finalTime
15,     0.44,   3,      300500,         400000
        42,     .31,    2,      900432,         100304
        41,     .2,     7,      192834,         200048
17,     0.234,  2,      2019481,        2182350
        8,      .1,     9,      1092834,        1190924
8,      0.241,  2,      2115120,        2159009
10,     0.092,  9,      2011234,        5001234
'''

data = re.sub(r'\t+', '*', data)
df = pd.read_csv(io.StringIO(data))

df.columns = [i.strip('*') for i in df.columns]
df.loc[df['ratio'].str.contains(r'\*'), 'ratio'] = np.nan
df['ratio'] = df['ratio'].ffill()
group_numbers = itertools.chain.from_iterable([[i+1]*v.shape[0] for i, (name,v) in enumerate(df.groupby('ratio', sort=False))])
df['ratio'] = list(group_numbers)
df = df.replace(r'\*', '', regex=True).set_index('ratio')

Урожайность :

      weight  flags initialTime finalTime
ratio                                    
1       0.44      3      300500    400000
1        .31      2      900432    100304
1         .2      7      192834    200048
2      0.234      2     2019481   2182350
2         .1      9     1092834   1190924
3      0.241      2     2115120   2159009
4      0.092      9     2011234   5001234
1
rahlf23 2 Июл 2019 в 05:16