2015-08-22 5 views
-1

У меня есть текстовый файл с 3 разделенными пробелами. Я пытаюсь найти для столбца А сколько столбцов B прошло. Значение в столбце B считается переходом, если в столбце C нет значения, кроме Pass в столбце C. В приведенном ниже примере данные PRO-16 считаются Fail, а PRO-18 - Pass и т. Д. Код мудрый Я попытался преобразовать это в dict и перебрать по внутреннему dict, чтобы узнать, имеет ли столбец C любой статус, другой, переданный для столбца B, но не повезло. благодарит за вашу помощь !!Python - итерация текстового файла и создание словаря словаря

Edit: это код, я использую, чтобы построить Dict, но читает только первую строку текстового файла: Myfile = pd.read_csv («SIT Req.txt»)

dataDict={} 
for line in myFile: 
     words = line.strip().split() 
     fa = words[0] 
     req = words[1] 
     state = words[2] 
     innerDict = dataDict.setdefault(fa, {}) 
     innerDict[req] = state 

FT PRO-16 Passed 
FT PRO-16 Failed 
FT PRO-18 Passed 
FT PRO-18 Passed 
FT PRO-19 Passed 
FT PRO-20 Failed 
FT PRO-21 No Run 
FT GR-01 Passed 
FT GR-02 Passed 
FT GR-02 Passed 
FT GR-02 Passed 
FT GR-03 Passed 
LE GR-19 Passed 
LE GR-19 Passed 
LE GR-20 Passed 
LE GR-21 Failed 
LE GR-22 Passed 
LE DEL-14 Passed 
LE DEL-14 Passed 
LE DEL-14 Passed 
LE DEL-15 Failed 
LE PRO-43 Failed 
LE PRO-45 Passed 
LE PRO-51 Passed 
CD GR-07 Passed 
CD GR-07 Failed 
CD GR-09 Passed 
CD GR-07 Passed 
CD GR-07 Passed 
CD GR-13 No Run 
CD GR-13 No Run 
CD GR-13 No Run 
CD GR-13 Failed 

ответ

1

Вы можете использовать collections.defaultdict для создания словаря с колонками а как ключи и каждый с defaultdict(list) для значения. Вложенный defaultdict(list) использует столбец B в качестве ключей и список значений из столбца C.

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

from pandas import read_csv 
from collections import defaultdict 

data = defaultdict(lambda : defaultdict(list)) 

df = read_csv('datafile', sep='\t') 
for a, b, c in df.values: 
    data[a][b].append(c) 

#from pprint import pprint 
#pprint(data.items()) 

# output the total number of passes for each "A" in which all runs of "B" passed. 
result_counts = {a: sum(1 for b in data[a] if all(c=='Passed' for c in data[a][b])) for a in data} 
print('Counts: {}'.format(result_counts)) 

# output for each "A" a list of all passed "B"s. 
result_passed = {a: list(b for b in data[a] if all(c=='Passed' for c in data[a][b])) for a in data} 
print('Passed: {}'.format(result_passed)) 

Выход

 
Counts: {'LE': 6, 'FT': 5, 'CD': 1} 
Passed: {'LE': ['DEL-14', 'PRO-45', 'PRO-51', 'GR-19', 'GR-22', 'GR-20'], 'FT': ['PRO-19', 'PRO-18', 'GR-01', 'GR-03', 'GR-02'], 'CD': ['GR-09']} 

Update

Что касается проблемы, с которой вы сталкиваетесь при итерации по кадру данных, есть две проблемы, которые я вижу. Во-первых, разделитель полей по умолчанию для read_csv является запятой. Кажется, что ваши данные разделены на вкладку. Во-вторых, вы не можете выполнять итерацию непосредственно по кадру данных. Попробуйте использовать один из следующих вариантов (я предлагаю несколько, поскольку они имеют разные характеристики):

df = pd.read_csv('SIT Req.tx', sep='\t') # note use of sep 

for a, b, c in df.values: 
    ... 
# or 
for i, a, b, c in df.itertuples(): 
    ... 
# or 
for i, row in df.iterrows(): 
    a, b, c = row 
    ... 

Update 2

Вот длинная версия словаря понимания, который выбирает те элементы из столбца B для которых все тесты прошли:

result_passed = {} 
for a in data: 
    result_passed[a] = [] 
    for b in data[a]: 
     passed = True 
     for c in data[a][b]: 
      if c != 'Passed': 
       passed = False 
       break 
     if passed: 
      result_passed[a].append(b) 

Вы можете получить лучшее понимание того, как это работает, глядя на содержание и структуру data словаря:

>>> from pprint import pprint 
>>> pprint(data.items()) 
[('LE', 
    defaultdict(<type 'list'>, {'DEL-15': ['Failed'], 'DEL-14': ['Passed', 'Passed', 'Passed'], 'PRO-43': ['Failed'], 'PRO-45': ['Passed'], 'PRO-51': ['Passed'], 'GR-19': ['Passed', 'Passed'], 'GR-22': ['Passed'], 'GR-21': ['Failed'], 'GR-20': ['Passed']})), 
('FT', 
    defaultdict(<type 'list'>, {'PRO-19': ['Passed'], 'PRO-20': ['Failed'], 'PRO-21': ['No Run'], 'PRO-16': ['Failed'], 'PRO-18': ['Passed', 'Passed'], 'GR-01': ['Passed'], 'GR-03': ['Passed'], 'GR-02': ['Passed', 'Passed', 'Passed']})), 
('CD', 
    defaultdict(<type 'list'>, {'GR-07': ['Passed', 'Failed', 'Passed', 'Passed'], 'GR-09': ['Passed'], 'GR-13': ['No Run', 'No Run', 'No Run', 'Failed']}))] 
+0

В выводе, который вы показали, PRO-16 отображается как проход, пока он должен быть сбой, так как он имеет соответствующее значение Failed, а также в столбце C – user5253936

+0

@ user5253936: извините, я не понял этих требований. Я обновил свой ответ - я думаю, что теперь он отвечает этим требованиям. – mhawke

+0

@ user5253936: также обновлено, чтобы показать, как перебирать рамку данных pandas, возвращаемую 'read_csv()'. – mhawke

0

Вы можете использовать defaultdict для этого:

from collections import defaultdict 
d = defaultdict(lambda : defaultdict(lambda : True)) 
for line in f: 
    words = line.split() 
    if words[2]!='Passed': 
     d[words[0]][words[1]] = False 

In [49]: d['FT']['PRO-18'] 
Out[49]: True 

In [50]: d['FT']['PRO-16'] 
Out[50]: False 
+0

его даст мне все столбцы B, которые прошли в столбце C. Хотя в соответствии с моим набором данных столбец B может иметь несколько ассоциированных значений в столбце C.Столбец B будет считаться пройденным, если все связанные значения передаются. Например, в наборе данных ниже PRO-16 не удалось при прохождении PRO 18 FT PRO-16 Прошел Ошибка FT PRO-16 FT PRO-18 Прошел FT PRO-18 прошел FT PRO-19 прошел FT PRO-20 Сбой FT PRO-21 Нет Пробег FT GR-01 Пройдено – user5253936

+0

@ user5253936 Что об этом? Если в C было поле «не прошло», оно будет ложным, в противном случае - True –

+0

Интересное решение. Вместо того, чтобы делать True или False, я могу добавить это в список. Задача состоит в том, что это будет очень большой файл, и я, возможно, не смогу проверять каждый отдельно. Таким образом, мой вывод может быть: [FT: [PRO-18, X, Y]], [LE: [A, B, C]] -----> где A, B, C передаются значения для LE из столбца B – user5253936

0

Из данных, которые у вас есть, элементы для столбца B все находятся в диапазоне от столбца A, то есть столбец A кажется смежным. Если это так, и как вы имеете дело с большим файлом, следующий подход может быть возможным:

import csv, itertools 

with open('input.csv', 'r') as f_input: 
    csv_input = csv.reader(f_input, delimiter=" ", skipinitialspace=True) 

    for k1, g1 in itertools.groupby(csv_input, key=lambda x: x[0]): 
     group = sorted(g1, key=lambda x: x[1]) 
     for k2, g2 in itertools.groupby(group, key=lambda x: x[1]): 
      if all((cols[2] == 'Passed' for cols in g2)): 
       print "%s %s Passed" % (k1, k2) 
      else: 
       print "%s %s Failed" % (k1, k2) 

Для данных, которые вы дали, отображаются следующие результаты:

FT GR-01 Passed 
FT GR-02 Passed 
FT GR-03 Passed 
FT PRO-16 Failed 
FT PRO-18 Passed 
FT PRO-19 Passed 
FT PRO-20 Failed 
FT PRO-21 Failed 
LE DEL-14 Passed 
LE DEL-15 Failed 
LE GR-19 Passed 
LE GR-20 Passed 
LE GR-21 Failed 
LE GR-22 Passed 
LE PRO-43 Failed 
LE PRO-45 Passed 
LE PRO-51 Passed 
CD GR-07 Failed 
CD GR-09 Passed 
CD GR-13 Failed 
+0

Большое спасибо Мартину .... это очень помогло – user5253936

Смежные вопросы