2012-04-21 4 views
1

非常に長い行からなるASCIIファイルを生成するためにPythonを使用しています。これは一例ラインである(のは、ファイル内の行100を言わせて、「[...]」行を短くするために私が追加されます):Pythonで予期しない空白が生成された文字列

{6 1,14 1,[...],264 1,270 2,274 2,[...],478 1,479 8,485 1,[...]} 

私はipythonで生成されたASCIIファイルを開く場合:

私が正しく印刷され、予想される行を取得行う
f = open('myfile','r') 
print repr(f.readlines()[99]) 

(「[...]」行を短くするために私が追加されます):

'{6 1,14 1,[...],264 1,270 2,274 2,[...],478 1,479 8,485 1,[...]}\n' 

逆に、私はこのファイルを開く場合それを読んでいると思われるプログラムが生成されますe例外は、478の後で予期しないペアについて不平を言う。 だから、vimでファイルを開こうとした。まだvimは問題ありませんが、vimで印刷された行をコピーして別のテキストエディタ(私の場合はTextMate)に貼り付けると、これは私が得た行です( '[...] ')行を短くするために私が追加されます。

{6 1,14 1,[...],264 1,270  2,274 2,[...],478 1,4  79 8,485 1,[...]} 

この行が実際にペアの後に478 1. を問題を持っている私が)...、cStringIOで、連結(さまざまな方法で自分のラインを生成しようとしましたしかし、私はいつもこの結果を得ています。 cStringIOを使用する場合は、例えば、行は(運で、私も、これを変更しようとしたにも関わらず)、以下のように生成される:

def _construct_arff(self,attributes,header,data_rows): 
    """Create the string representation of a Weka ARFF file. 
    *attributes* is a dictionary with attribute_name:attribute_type 
     (e.g., 'num_of_days':'NUMERIC') 
    *header* is a list of the attributes sorted 
     (e.g., ['age','name','num_of_days']) 
    *data_rows* is a list of lists with the values, sorted as in the header 
     (e.g., [ [88,'John',465],[77,'Bob',223]]""" 

    arff_str = cStringIO.StringIO() 
    arff_str.write('@relation %s\n' % self.relation_name) 

    for idx,att_name in enumerate(header): 
    try: 
     name = att_name.replace("\\","\\\\").replace("'","\\'") 
     arff_str.write("@attribute '%s' %s\n" % (name,attributes[att_name])) 
    except UnicodeEncodeError: 
     arff_str.write('@attribute unicode_err_%s %s\n' 
        % (idx,attributes[att_name])) 

    arff_str.write('@data\n') 
    for data_row in data_rows: 
    row = [] 
    for att_idx,att_name in enumerate(header): 
     att_type = attributes[att_name] 
     value = data_row[att_idx] 
     # numeric attributes can be sparse: None and zeros are not written 
     if ((not att_type == constants.ARRF_NUMERIC) 
      or not ((value == None) or value == 0)): 
     row.append('%s %s' % (att_idx,value)) 
    arff_str.write('{' + (','.join(row)) + '}\n') 
    return arff_str.getvalue() 

UPDATE:あなたから見ることができるようにこの関数は、与えられたデータセットを特殊なarffファイルフォーマットに変換します。私が作成した属性の1つに数字が文字列として含まれていることに気付きました(たとえば、1ではなく「1」)。これらの数値を整数に強制することによって:

features[name] = int(value) 

arffファイルを正常に再作成しました。しかし、値であるこれが* att_idx *のフォーマットにどのように影響するかはわかりませんが、これは@JohnMachinと@gnibblerによって指摘されているように(常に答えています、btw) 。だから、私のコードが今実行されていても、なぜこれが起こるのかまだ分かりません。値が正しくに変換されないと、他の何らかのフォーマットに影響を与えますか?

This fileに不適切な形式のバージョンが含まれています。

+0

フォーマット文字列を使用して数字を挿入するときに、なぜ '%s'の代わりに '%d'を使用してみませんか?これは問題を解決するか、問題を明らかにする必要があります(恐らくどこかにあり、 'data_row [att_idx]'からコピーされます) –

+0

テキストファイルの3の後ろに隠しタブ文字がありますか?7は本当に4スペース境界にあります。 –

+4

'repr'を使って、文字列に何が入っているかを正確に確認してください。 – agf

答えて

11

組み込み関数reprはあなたの友人です。あなたがあなたのファイルに持っているものを明白に表示します。

は、この操作を行います。

f = open('myfile','r') 
print repr(f.readlines()[99]) 

をして結果を表示するためにあなたの質問を編集します。 と表示されたコードでは、それが生成されていない可能性があります。 37の値はatt_idxの値でなければならず、これはenumerate()から来て、intでなければなりません。このintを%sでフォーマットしています... 37は3rubbish7にはなりません。また、att_idxを0、1などの順序で生成する必要がありますが、多くの値が欠落しており、ループ内に条件付きのものはありません。

実際に実行したコードを表示してください。

更新

そして再び、このコードは実行されません。

for idx,att_name in enumerate(header): 
    arff_str.write("@attribute '%s' %s\n" % (name,attributes[att_name])) 

nameが定義されていないからです。おそらくatt_nameを意味します。

おそらく、私たちは消費者を邪魔しているかもしれないものを自分たちのために見ることができるように、Web上の出力ファイルのコピーを投稿します(巨大ならzipされます)。あなたの質問を編集して、どのラインが問題を呈しているかを教えてください。

ちなみに、データの一部は整数ではなく文字列であり、intにデータを強制すると、問題はなくなります。features[name] = int(value) ...「機能」とは何ですか?名前は何ですか'??

これらの文字列のいずれかは、strの代わりにunicodeですか?

アップデート2

どのライン(S)展示(S)問題に供給しない情報(ネット上に掲載不良ファイルの後)。 (コラム80で包まれた)

import re, sys 
# sample data line: 
# {40 1,101 3,319 2,375 2,525 2,530 bug} 
# Looks like all data lines end in ",530 bug}" or ",530 other}" 
pattern1 = r"\{(?:\d+ \d+,)*\d+ \w+\}$" 
matcher1 = re.compile(pattern1).match 
pattern2 = r"\{(?:\d+ \d+,)*" 
matcher2 = re.compile(pattern2).match 
bad_atts = re.compile(r"\D\d+\s+\W").findall 
got_data = False 
for lino, line in enumerate(open(sys.argv[1], "r"), 1): 
    if not got_data: 
     got_data = line.startswith('@data') 
     continue 
    if not matcher1(line): 
     print 
     print lino, repr(line) 
     m = matcher2(line) 
     if m: 
      print "OK up to offset", m.end() 
      print bad_atts(line) 

サンプル出力:

581 '{2 1,7 1,9 1,12 1,13 1,14 1,15 1,16 1,17 1,18 1,21 1,22 1,24 1,25 1,26 1,27 
1,29 1,32 1,33 1,36 1,39 1,40 1,44 1,48 1,49 1,50 1,54 1,57 1,58 1,60 1,67 1,68 
1,69 1,71 1,74 1,75 1,76 1,77 1,80 1,88 1,93 1,101 ,103 6,104 2,109 20,110 3,11 
2 2,114 1,119 17,120 4,124 39,128 5,137 1,138 1,139 1,162 1,168 1,172 18,175 1,1 
76 6,179 1,180 1,181 2,185 2,187 9,188 8,190 1,193 1,195 2,196 4,197 1,199 3,201 
3,202 4,203 5,206 1,207 2,208 1,210 2,211 1,212 5,213 1,215 2,216 3,218 2,220 2 
,221 3,225 8,226 1,233 1,241 4,242 1,248 5,254 2,255 1,257 4,258 4,260 1,266 1,2 
68 1,269 3,270 2,271 5,273 1,276 1,277 1,280 1,282 1,283 11,285 1,288 1,289 1,29 
6 8,298 1,299 1,303 1,304 11,306 5,308 1,309 8,310 1,315 3,316 1,319 11,320 5,32 
1 11,322 2,329 1,342 2,345 1,349 1,353 2,355 2,358 3,359 1,362 1,367 2,368 1,369 
1,373 2,375 9,377 1,381 4,382 1,383 3,387 1,388 5,395 2,397 2,400 1,401 7,407 2 
,412 1,416 1,419 2,421 2,422 1,425 2,427 1,431 1,433 7,434 1,435 1,436 2,440 1,4 
49 1,454 2,455 1,460 3,461 1,463 1,467 1,470 1,471 2,472 7,477 2,478 11,479 31,4 
82 6,485 7,487 1,490 2,492 16,494 2,495 1,497 1,499 1,501 1,502 1,503 1,504 11,5 
06 3,510 2,515 1,516 2,517 3,518 1,522 4,523 2,524 1,525 4,527 2,528 7,529 3,530 
bug}\n' 
OK up to offset 203 
[',101 ,'] 

709 '{101 ,124 2,184 1,188 1,333 1,492 3,500 4,530 bug}\n' 
OK up to offset 1 
['{101 ,'] 

だから、属性のように見えることが判明したように、何の行は、私は、このチェックスクリプトを書いた属性479で説明した問題を示しませんでしたatt_idx == 101には、空の文字列''が含まれることがあります。この属性の扱い方を整理する必要があります。別に

if ((not att_type == constants.ARRF_NUMERIC) 
     or not ((value == None) or value == 0)): 

:あなたはこのビザンチンコードを巻き戻されている場合それはあなたの思考を助ける「虚辞削除」のコードが実行されないこと。それはARRFない、ARFFする必要がありますへの

if value or att_type != constants.ARFF_NUMERIC: 

または多分ちょうどif value:None0、および""のすべてを除外します。 att_idx == 101がARFFファイルのヘッダーに文字列型を付与された属性「優先順位」に対応していることに注意してください:

[line 103] @attribute 'priority' STRING 

ところで、features[name] = int(value)についてのあなたの声明「固定」の問題は非常に疑わしいです。 int("")は例外を発生させます。

この末尾の警告を読むのに役立ちます。wiki section about sparse ARFF files

+0

フィーチャは、フィーチャの名前(変数 'ヘッダ'および '属性'のように)をキーとして、ディクショナリ値(フィーチャ値はdata_rowsに表示されるフィーチャ値)を持つディクショナリです。 –

+0

私が間違ってフォーマットされたファイルをアップロードしましたが、データを 'int'に強制しないと生成されました。 –

関連する問題