2010-01-02 161 views
0

我有CSV文件中的数据。其中一列列出了人员姓名,该列中的所有行都提供了有关该人员的一些描述性属性,直到出现下一个人员名称。我可以通过LTYPE列判断该行何时具有名称或属性,该列中的N表示该行中的NAME值实际上是一个名称,该列中的A表示该NAME列中的数据是一个属性。属性被编码,我有600K行的数据。这是一个示例。该数据分组,每一组的befinning由RID复位表示为1Python使用基于索引的列表

{'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名单,因为在循环之前完成它被添加。因此,要获得分组的属性列表我要运行

newAttribute.append(tempAttribute) 

但即使如此,我似乎无法找到一个干净的方式来增加我必须做的两个步骤的属性。首先,我创建了nameIndex位置为关键和属性的值

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

我循环通过列表,一旦在属性穿上名行

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 2010-01-02 20:11:57

回答

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 2010-01-02 21:28:26

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

我非常感谢您的帮助,我从您提供的代码中学到了很多东西。我标记了你的答案,但我把Alex的标记标记为已接受,因为我必须添加两行来获得我正在寻找的内容。我在join_person_attributes函数中的attributes =赋值之后和new_row ['PERSON_NAME'] = pname之后添加了pname =''.join(行['NAME']用于组中的行,如果row ['LTYPE'] =='N') new_row赋值语句。我真的很感谢你的回答,并且学到了很多东西。谢谢 – PyNEwbie 2010-01-02 21:31:35