2010-01-02 7 views
0

У меня есть данные в CSV-файле. В одном из столбцов указывается имя человека, и все строки, которые следуют в этом столбце, содержат некоторые описательные атрибуты об этом человеке до появления следующего имени человека. Я могу сказать, когда строка имеет имя или атрибут столбцом LTYPE, N в этом столбце указывает, что в этой строке значение NAME на самом деле является именем, A в этом столбце указывает, что данные в столбце NAME являются атрибутом , Атрибуты закодированы, и у меня есть 600K строк данных. Вот пример. Данные сгруппированы и befinning из каждой группы указывается РИД перенастройки на 1.Python Работа со списками на основе индексов

{'LTYPE': 'N', 'RID': '1', 'NAME': 'Jason Smith'} 
{'LTYPE': 'A', 'RID': '2', 'NAME': 'DA'} 
{'LTYPE': 'A', 'RID': '3', 'NAME': 'B'} 
{'LTYPE': 'N', 'RID': '4', 'NAME': 'John Smith'} 
{'LTYPE': 'A', 'RID': '5', 'NAME': 'BC'} 
{'LTYPE': 'A', 'RID': '6', 'NAME': 'CB'} 
{'LTYPE': 'A', 'RID': '7', 'NAME': 'DB'} 
{'LTYPE': 'A', 'RID': '8', 'NAME': 'DA'} 
{'LTYPE': 'N', 'RID': '9', 'NAME': 'Robert Smith'} 
{'LTYPE': 'A', 'RID': '10', 'NAME': 'BC'} 
{'LTYPE': 'A', 'RID': '11', 'NAME': 'DB'} 
{'LTYPE': 'A', 'RID': '12', 'NAME': 'CB'} 
{'LTYPE': 'A', 'RID': '13', 'NAME': 'RB'} 
{'LTYPE': 'A', 'RID': '14', 'NAME': 'VC'} 
{'LTYPE': 'N', 'RID': '15', 'NAME': 'Harvey Smith'} 
{'LTYPE': 'A', 'RID': '16', 'NAME': 'SA'} 
{'LTYPE': 'A', 'RID': '17', 'NAME': 'AS'} 
{'LTYPE': 'N', 'RID': '18', 'NAME': 'Lukas Smith'} 
{'LTYPE': 'A', 'RID': '19', 'NAME': 'BC'} 
{'LTYPE': 'A', 'RID': '20', 'NAME': 'AS'} 

Я хочу создать следующее:

{'PERSON_ATTRIBUTES': 'DA B ', 'LTYPE': 'N', 'RID': '1', 'PERSON_NAME': 'Jason Smith', 'NAME': 'Jason Smith'} 
{'PERSON_ATTRIBUTES': 'DA B ', 'LTYPE': 'A', 'RID': '2', 'PERSON_NAME': 'Jason Smith', 'NAME': 'DA'} 
{'PERSON_ATTRIBUTES': 'DA B ', 'LTYPE': 'A', 'RID': '3', 'PERSON_NAME': 'Jason Smith', 'NAME': 'B'} 
{'PERSON_ATTRIBUTES': 'BC CB DB DA ', 'LTYPE': 'N', 'RID': '4', 'PERSON_NAME': 'John Smith', 'NAME': 'John Smith'} 
{'PERSON_ATTRIBUTES': 'BC CB DB DA ', 'LTYPE': 'A', 'RID': '5', 'PERSON_NAME': 'John Smith', 'NAME': 'BC'} 
{'PERSON_ATTRIBUTES': 'BC CB DB DA ', 'LTYPE': 'A', 'RID': '6', 'PERSON_NAME': 'John Smith', 'NAME': 'CB'} 
{'PERSON_ATTRIBUTES': 'BC CB DB DA ', 'LTYPE': 'A', 'RID': '7', 'PERSON_NAME': 'John Smith', 'NAME': 'DB'} 
{'PERSON_ATTRIBUTES': 'BC CB DB DA ', 'LTYPE': 'A', 'RID': '8', 'PERSON_NAME': 'John Smith', 'NAME': 'DA'} 
{'PERSON_ATTRIBUTES': 'BC DB CB RB VC ', 'LTYPE': 'N', 'RID': '9', 'PERSON_NAME': 'Robert Smith', 'NAME': 'Robert Smith'} 
{'PERSON_ATTRIBUTES': 'BC DB CB RB VC ', 'LTYPE': 'A', 'RID': '10', 'PERSON_NAME': 'Robert Smith', 'NAME': 'BC'} 
{'PERSON_ATTRIBUTES': 'BC DB CB RB VC ', 'LTYPE': 'A', 'RID': '11', 'PERSON_NAME': 'Robert Smith', 'NAME': 'DB'} 
{'PERSON_ATTRIBUTES': 'BC DB CB RB VC ', 'LTYPE': 'A', 'RID': '12', 'PERSON_NAME': 'Robert Smith', 'NAME': 'CB'} 
{'PERSON_ATTRIBUTES': 'BC DB CB RB VC ', 'LTYPE': 'A', 'RID': '13', 'PERSON_NAME': 'Robert Smith', 'NAME': 'RB'} 
{'PERSON_ATTRIBUTES': 'BC DB CB RB VC ', 'LTYPE': 'A', 'RID': '14', 'PERSON_NAME': 'Robert Smith', 'NAME': 'VC'} 
{'PERSON_ATTRIBUTES': 'SA AS ', 'LTYPE': 'N', 'RID': '15', 'PERSON_NAME': 'Harvey Smith', 'NAME': 'Harvey Smith'} 
{'PERSON_ATTRIBUTES': 'SA AS ', 'LTYPE': 'A', 'RID': '16', 'PERSON_NAME': 'Harvey Smith', 'NAME': 'SA'} 
{'PERSON_ATTRIBUTES': 'SA AS ', 'LTYPE': 'A', 'RID': '17', 'PERSON_NAME': 'Harvey Smith', 'NAME': 'AS'} 
{'PERSON_ATTRIBUTES': 'BC AS ', 'LTYPE': 'N', 'RID': '18', 'PERSON_NAME': 'Lukas Smith', 'NAME': 'Lukas Smith'} 
{'PERSON_ATTRIBUTES': 'BC AS ', 'LTYPE': 'A', 'RID': '19', 'PERSON_NAME': 'Lukas Smith', 'NAME': 'BC'} 
{'PERSON_ATTRIBUTES': 'BC AS ', 'LTYPE': 'A', 'RID': '20', 'PERSON_NAME': 'Lukas Smith', 'NAME': 'AS'} 

Я начал с получения позиции индекса из LTYPE

nameIndex=[] 
attributeIndex=[] 
for line in thedata: 
    if line['LTYPE']=='N': 
     nameIndex.append(int(line["RID"])-1) 
    if line['LTYPE']=='A': 
     attributeIndex.append(int(line["RID"])-1) 

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

for counter, row in enumerate(thedata): 
    if counter in nameIndex: 
     row['PERSON_NAME']=row['NAME'] 
     person_NAME=row['NAME'] 
    if counter not in nameIndex: 
     row['PERSON_NAME']=person_NAME 

Я изо всех сил, чтобы определить и назначить список атрибутов для каждого человека.

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

newAttribute=[] 
for counter, row in enumerate(thedata): 
    if counter in attributeIndex: 
     tempAttribute=tempAttribute+' '+row['NAME'] 

    if counter not in attributeIndex: 
     if counter==0: 
      tempAttribute="" 
      pass 
     if counter!=0: 
      newAttribute.append(tempAttribute.lstrip()) 
      tempAttribute="" 

одна проблемы с моим подходом является то, что я до сих пор добавить последнюю группу в список новыйАтрибута, так как цикл завершается до он добавляется. Таким образом, чтобы получить список сгруппированных атрибутов я должен запустить

newAttribute.append(tempAttribute) 

Но даже тогда я не могу найти чистый способ добавить атрибуты, которые я должен сделать это в два этапа. Во-первых, создать словарь с позиции nameIndex в качестве ключа и атрибуты, как значения

tempDict={} 
for each in range(len(nameIndex)): 
    tempdict[nameIndex[each]]=newAttribute[each] 

I цикл по списку раз положить в атрибуте на имя линии

for counter,row in enumerate(thedata): 
    if counter in tempDict: 
     thedata[counter]['TA']=tempDict[counter] 

, а затем я пройти через это еще раз проверить, если ключ «TA» существует и используя существование, чтобы установить PERSON_ATTRIBUTE ключ

for each in thedata: 
    if each.has_key('TA'): 
     each['PERSON_ATTRIBUTES']=each['TA'] 
     holdAttribute=each['TA'] 
    else: 
     each['PERSON_ATTRIBUTES']=holdAttribute 

Там надо быть уборщиком способ думать об этом, и поэтому я было интересно, хочет ли кто-нибудь указать мне в сторону некоторых функций, которые я мог бы прочитать, что позволит мне очистить этот код. Я знаю, что мне еще нужно сбросить ключ «TA», но я подумал, что занял достаточно места.

+1

Форматирование. Вы, похоже, не знаете о 'else' /' elif'? – ephemient

ответ

2

я предлагаю другой, индекс свободного подхода, основанного на itertools.groupby:

import itertools, operator 

data = [ 
{'LTYPE': 'N', 'RID': '1', 'NAME': 'Jason Smith'}, 
{'LTYPE': 'A', 'RID': '2', 'NAME': 'DA'}, 
{'LTYPE': 'A', 'RID': '3', 'NAME': 'B'}, 
{'LTYPE': 'N', 'RID': '4', 'NAME': 'John Smith'}, 
{'LTYPE': 'A', 'RID': '5', 'NAME': 'BC'}, 
{'LTYPE': 'A', 'RID': '6', 'NAME': 'CB'}, 
{'LTYPE': 'A', 'RID': '7', 'NAME': 'DB'}, 
{'LTYPE': 'A', 'RID': '8', 'NAME': 'DA'}, 
] 

for k, g in itertools.groupby(data, operator.itemgetter('LTYPE')): 
    if k=='N': 
    person_name_record = next(g) 
    else: 
    attribute_records = list(g) 
    person_attributes = ' '.join(r['NAME'] for r in attribute_records) 
    addfields = dict(PERSON_ATTRIBUTES=person_attributes, 
        PERSON_NAME=person_name_record['NAME']) 
    person_name_record.update(addfields) 
    for r in attribute_records: r.update(addfields) 

for r in data: print r 

Это печатает желаемые результаты для первых парных людей (и каждый человек рассматривается отдельно, поэтому он должен работать одинаково для нескольких сотен тысяч человек ;-).

+0

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

1

Я бы разделил это на две задачи.

Сначала разделите thedata на группы из LTYPE=N строк и LTYPE=A строк, которые следуют за ним.

def group_name_and_attributes(thedata): 
    group = [] 
    for row in thedata: 
     if row['LTYPE'] == 'N': 
      if group: 
       yield group 
      group = [row] 
     else: 
      group.append(row) 
    if group: 
     yield group 

Далее следует отбирать каждую группу отдельно и собирать общие атрибуты для каждого; легко добавить атрибуты суммы в каждую строку по желанию.

def join_person_attributes(thedata): 
    for group in group_name_and_attributes(thedata): 
     attributes = ' '.join(row['NAME'] for row in group if row['LTYPE'] == 'A') 
     for row in group: 
      new_row = row.copy() 
      new_row['PERSON_ATTRIBUTES'] = attributes 
      yield new_row 

new_data = list(join_person_attributes(thedata)) 

Конечно, вы могли бы сделать это изменить строки в месте, или возвращать только одну строку в группе, или ...

+0

Я очень ценю вашу помощь, и я многому научился от игры с кодом, который вы предоставили. Я отметил ваш ответ, но я отметил, что Алекс принят, потому что мне пришлось добавить две строки к твоей, чтобы получить то, что я искал. Я добавил pname = '' .join (строка ['NAME'] для строки в группе, если строка ['LTYPE'] == 'N') после атрибута = назначение в функции join_person_attributes и new_row ['PERSON_NAME'] = pname after оператор присваивания new_row. Я действительно ценю ваш ответ и многому научился. Спасибо – PyNEwbie

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