1

全て

単純な ARFF ファイルを解析するコードを見つけたので、データが次のようなスパース ARFF に合うように変更したい:

@data
{0 12,4 37,8 First,20 'Some Thing'} 
{0 12,13 First,28 'Some Thing'}

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

def ParseFromSimpleARFF(data):
    arffFormat = Forward()
    E = CaselessLiteral("E")
    comment = '%' + restOfLine
    relationToken = Keyword('@RELATION', caseless=True)
    dataToken = Keyword('@DATA', caseless=True)
    attribToken = Keyword('@ATTRIBUTE', caseless=True)
    ident = Word( alphas, alphanums + '_-' ).setName('identifier')
    relation = Suppress(relationToken) \
               + ident.setResultsName('relation')    
    classDomain = Suppress('{') \
                  + Group(delimitedList(ident.setResultsName('domain'))).setResultsName('domains') + Suppress('}')
    attribute = Group(Suppress(attribToken)
                + Word(alphas).setResultsName('attrname')+(Word(alphas)|classDomain).setResultsName('type')).setResultsName('attribute')            
    arithSign = Word("+-",exact=1)
    realNum = Combine( Optional(arithSign) 
              + (Word( nums ) + "." + Optional( Word(nums) )|( "." + Word(nums) )) 
              + Optional( E + Optional(arithSign) + Word(nums) ))

    **#dataList = Group(delimitedList(realNum|ident)).setResultsName('record')
    dataList = Suppress('{') + Group( delimitedList(realNum|ident)).setResultsName('record')  + Suppress('}')**
    arffFormat << ( relation
                   + OneOrMore(attribute).setResultsName('attributes')
                   + dataToken
                   + OneOrMore(dataList).setResultsName('records')).setResultsName('arffdata')

    simpleARFF = arffFormat
    simpleARFF.ignore(comment)
    tokens =  simpleARFF.parseString(data) 
    return tokens

しかし、それは機能しません

空白を識別するようにプログラムに指示する必要があると思いますが、方法がわかりません

本当にありがとう

4

1 に答える 1

2

ダメダメダメ!pyparsing の大きな部分は、「空白が発生する」ことです! インデントベースの解析または行指向のデータで何かトリッキーなことをしている場合を除き、パーサー定義から空白を除外してください。

あなたの問題は、あなたが dataList として定義しているものは、あなたが与えているリストと一致しないということです。リスト内のコンマで区切られた各項目は値のペアであり、数値または引用符付き文字列を許可しているようです。したがって、dataList を次のように定義します。

dataCell = realNum|ident|quotedString
dataList = Suppress('{') + Group( delimitedList(Group(dataCell + dataCell)))  + Suppress('}')

その他のビット:

  • arffFormat を Forward() として宣言する必要はありません。これは、データが再帰構造内にネストされる場合、つまりサブデータを含むデータの場合にのみ必要です。あなたの例にはそれがありません。最後にarffFormatを定義するだけですarffFormat = (...etc.

  • x.setResultsName('name')は単純に に置き換えx('name')られ、パーサー コードが本当にクリーンアップされます

  • realNum (小数点が必要) を定義しますが、サンプルには整数しかありません。ローカライズされた正規表現を使用することを支持して、realNum 型の式を構築することから離れました:realNum = Regex(r"[+-]?\d+(\.\d*)?([Ee][+-]?\d+)?")は、整数または実数を受け入れる式を提供します。これにより、arithSign などの他の気を散らす要素を削除することもできます。

また、結果の名前を使いすぎている可能性もあります。これにより、データに対するかなりの洞察が得られ、最後に非常に簡単にナビゲートできる構造が得られると思います。

arffFormat = ( relation
               + OneOrMore(attribute)('attributes')
               + dataToken
               + OneOrMore(dataList)('records'))('arffdata')
于 2011-06-07T15:11:58.063 に答える