2016-10-26 3 views
1

Imagine у ​​нас есть большой файл с рядами следующимСчитывает данные в куски и держать одну строку для каждого ID в Python

ID  value  string 
1  105  abc 
1  98  edg 
1  100  aoafsk 
2  160  oemd 
2  150  adsf 
... 

Say файл с именем file.txt и отделена вкладки.

Я хочу сохранить наибольшее значение для каждого идентификатора. Ожидаемый выход

ID  value  string 
1  105  abc 
2  160  oemd 
... 

Как я могу прочитать его кусками и обработать данные? Если я прочитаю данные в кусках, как я могу убедиться, что в конце каждого фрагмента записи будут заполнены для каждого ID?

ответ

0

Следите данных в словаре этого формата:

data = { 
    ID: [value, 'string'], 
} 

Как вы читаете каждую строку из файла, если посмотреть, что ID уже в Словаре. Если нет, добавьте его; если это так, и текущий идентификатор больше, замените его в dict.

В конце ваш дикт должен иметь самый большой идентификатор.

# init to empty dict 
data = {} 

# open the input file 
with open('file.txt', 'r') as fp: 

    # read each line 
    for line in fp: 

      # grab ID, value, string 
      item_id, item_value, item_string = line.split() 

      # convert ID and value to integers 
      item_id = int(item_id) 
      item_value = int(item_value) 

      # if ID is not in the dict at all, or if the value we just read 
      # is bigger, use the current values 
      if item_id not in data or item_value > data[item_id][0]: 
       data[item_id] = [item_value, item_string] 

for item_id in data: 
    print item_id, data[item_id][0], data[item_id][1] 

Словари не выполняют какой-либо конкретный порядок их содержаний, так что в конце вашей программы, когда вы получаете данные обратно из Словаря, она не может быть в том же порядке, что и исходный файл (т.е. сначала вы увидите ID 2, а затем ID 1).

Если это имеет значение для вас, вы можете использовать OrderedDict, который сохраняет первоначальный порядок вставки элементов.

(У вас есть что-то конкретное в виду, когда вы сказали «прочитанный кусками»? Если вы имели в виду определенное количество байтов, тогда вы можете столкнуться с проблемами, если граница куска падает в середине слово ...)

+0

Ваш ответ работает правильно. Один вопрос.Какой из них более эффективен: обрабатывать по строкам или читать в кусках и обрабатывать фрагменты куском или читать файл и обрабатывать их сразу (если позволяет память)? Мне все еще интересно, как будут работать куски. Поэтому я оставлю вопрос открытым на некоторое время. Если лучшего ответа не будет, возьмите. Благодарю. – Rwitch

+0

Я сомневаюсь, что будет большая разница, так как ОС уже выполняет буферизацию ввода под капотом. –

0

Код

import csv 
import itertools as it 
import collections as ct 


with open("test.csv") as f:         
    reader = csv.DictReader(f, delimiter=" ")    # 1 
    for k, g in it.groupby(reader, lambda d: d["ID"]):  # 2 
     print(max(g, key=lambda d: float(d["value"])))  # 3 

# {'value': '105', 'string': 'abc', 'ID': '1'} 
# {'value': '160', 'string': 'oemd', 'ID': '2'} 

Детали

Блок with обеспечивает безопасное открытие и закрытие файла f. Файл итерируется, позволяя вам перебрать его или в идеале применить itertools.

  1. Для каждой линии f, csv.DictReader разбивает данные и сохраняет информацию заголовка-строки в качестве значения ключа пар словаря, например. [{'value': '105', 'string': 'abc', 'ID': '1'}, ...

  2. Эти данные являются итерабельными и переданы в groupby, что куски всех данных по ID. См. this post from more details on how groupby works.

  3. Встраиваемый встроенный в специальную ключевую функцию возвращает диктофоны с наибольшим "value". См. this tutorial for more details on the max() function.