0

次のようなテキストファイルがあります

First col, Second col, Third col, Fourth col,...

これに似ています:

Johnny, Rodgers, ID1, 18th July,...   
Johnny, Rodgers, ID1, 18th July,...  
Pat, Bryant, ID2, 29th April,...   
Pat, Bryant, ID2, 9th May,... 
Jim, Williams, ID3, 10th March,...  
Jim, Williams, ID3, 17th March,...   
Jim, Williams, ID3, 21st March,...
etc   

3列目に繰り返しがあるかどうかを確認したいのですが、その場合、3列目に繰り返しがある行で4列目も同じかどうかを確認します。列 3 と列 4 も同じ場合は両方の行 (行全体) を削除し、列 4 が異なる場合は結果を保存します。その後、結果を印刷/保存します。

これは、
* 行 1、2 の列 3 が同じ値で、列 4 も同じ値である場合は、両方の行を削除します
* 行 3 と 4 の列 3 が同じ値で、列 4 が異なる場合は、行とカウント +1
* 行 5、6、および 7 の列 3 の値が同じで、列 4 が異なる場合、行を出力して +1 を数えます

実行後、結果は次のようになります

Pat, Bryant, ID2, 29th April,...   
Pat, Bryant, ID2, 9th May,... 
Jim, Williams, ID3, 10th March,...  
Jim, Williams, ID3, 17th March,...   
Jim, Williams, ID3, 21st March,...

counter = 2 #Number of different ID present

私の考えでは、2 つのリストを作成してそこに行を格納することですが、ターゲットを設定して同時に他の列を比較することに成功していません。また、現在のロジックでループしてポップする必要がありますが、うまくいきません。

val = []
duplicated = []

with open('file.txt', 'rt') as myf.
     for line in myf:
            col = line.stip():split(',')
            if col[2] not in val:
                val.append( THE ROW HERE ) #How to copy and parse the row?
            else:
                duplicated.append( THE ROW HERE ) #Same question
#Comparisons

for x in value:
    if x in dupl:
        value.pop(x)
        dupl.pop(x)

counter = len(val) #Counter of total cases not erased
val.extend(duplicated)

### I would like to print the whole set of rows ordered by the 3rd col

for element in val:
    print element

print "counter of cases: " , counter

コーディングを改善するためのヘルプと提案は大歓迎です。

4

2 に答える 2

1

私はあなたのコード例から始めて、マージして削除する行が隣接していると仮定しました。比較のために前の行の値を保持し、オプションで最後の行を追加します。

さまざまな ID をカウントするためにセットを使用します。

また、現在のロケールで月の完全な名前を持つデータとして取得される 3 番目のフィールドと 4 番目のフィールドに保持された行の並べ替えも実装しました。

あなたの例でテストしたところ、削除する2行が隣接していれば、入力行がシャッフルされていても、出力はあなたが求めたものです。

コードは次のとおりです。

import re
import datetime
val = []

old = None
oldcount = 0
oldcols = None
counter = 0

ids = set()

with open('file.txt', 'rt') as myf:
     for line in myf:
            cols = line.strip().split(',')
            if (old is not None) and (oldcols[2] == cols[2]) \
                   and (oldcols[3] == cols[3]):
                oldcount += 1
            else:
                if oldcount == 1:
                    val.append(old)
                    ids.add(cols[2])
                old = line.strip()
                oldcount = 1
                oldcols = cols

if oldcount == 1:
    val.append(old)
    ids.add(cols[2])

### I would like to print the whole set of rows ordered by the 3rd col
rx = re.compile('\s*([ 0-9]{2}).. *(\w*)')
val.sort(key = lambda x: datetime.datetime.strptime(
    rx.sub('\g<1> \g<2>',x.split(',')[3]),'%d %B'))
val.sort(key = lambda x: x.split(',')[2])
for element in val:
    print (element)

print ("counter of cases: " , len(ids))
于 2014-08-11T15:59:06.777 に答える
1

それらが常に隣接していると仮定し、サンプルデータを使用すると:

import csv

with open(fn, 'r') as fin:
    reader=csv.reader(fin, skipinitialspace=True)
    header=next(reader)
    data={k:[] for k in header}
    for row in reader:
        row_di={k:v for k,v in zip(header, row)}
        if (all(len(data[e]) for e in header) 
               and row_di['Third col']==data['Third col'][-1] 
               and row_di['Fourth col']==data['Fourth col'][-1]):
            for e in header:
                data[e].pop()
        else:
            for e in header:
                data[e].append(row_di[e])

>>> data
{'Second col': ['Bryant', 'Bryant', 'Williams', 'Williams', 'Williams'], 'First col': ['Pat', 'Pat', 'Jim', 'Jim', 'Jim'], 'Fourth col': ['29th April', '9th May', '10th March', '17th March', '21st March'], 'Third col': ['ID2', 'ID2', 'ID3', 'ID3', 'ID3'], '...': ['...   ', '... ', '...  ', '...   ', '...']}

それをあなたのフォーマットで印刷する:

unique_ids=set(data['Third col'])    

while True:                        
    try:    
        print ', '.join([data[e].pop(0) for e in header])
    except IndexError:
        break     
print 'Unique IDs:', len(unique_ids)         

版画:

Pat, Bryant, ID2, 29th April, ...   
Pat, Bryant, ID2, 9th May, ... 
Jim, Williams, ID3, 10th March, ...  
Jim, Williams, ID3, 17th March, ...   
Jim, Williams, ID3, 21st March, ...
Unique IDs: 2

ノート:

  1. 通常、csv データにはcsv モジュールを使用することをお勧めします。
  2. a を使用set(iterable)して iterable 内の一意のエントリの数を取得します。
  3. 非常に多くのデータがある場合は、リストの dict ではなく、dequesの dict を使用することを検討してください。Deques は、この実装が依存している pop を使用すると、はるかに高速になります。
于 2014-08-11T14:55:07.000 に答える