9

Python で希望する形式でデータを取得するのに問題があります。

基本的に、バイナリデータを読み取り、そのデータのプロットと分析のための機能を提供するプログラムがあります。

私のデータには、主な見出しと、任意の数のさまざまなデータ型である可能性のある小見出しがあります。

たとえば、次のように自分のデータにアクセスできるようにしたいと思います。

>>> a = myDatafile.readit()
>>> a.elements.hydrogen.distributionfunction
(a big array)
>>> a.elements.hydrogen.mass
1
>>> a.elements.carbon.mass
12

しかし、実行時までアトムの名前はわかりません。

たとえば、すべてのアトム名を読み込んだ後、namedtuple を使用してみました。

self.elements = namedtuple('elements',elementlist)

elementlist は、たとえば ('hydrogen','carbon') などの文字列のリストです。しかし、問題は、たとえば次のようにこれらをネストできないことです。

for i in range(0,self.nelements):
    self.elements[i] = namedtuple('details',['ux','uy','uz','mass','distributionfunction'])

そして、たとえば次の方法で値にアクセスできます

self.elements.electron.distributionfunction.

多分私はこれを完全に間違っています。私はPythonにかなり慣れていません。変数に動的に名前を付けることに煩わされなければ、これは簡単にできると思います。

私が達成しようとしていることを明確にしたことを願っています!

4

4 に答える 4

5

データを知らなければ、一般的な解決策しか提供できません。

最初の 2 行に見出しとサブ見出しが含まれていることを考慮して、何らかの方法で階層を決定しました。必要なのは、階層辞書を作成することだけです。

たとえば、例を拡張する

data.elements.hydrogen.distributionfunction
data.elements.nitrogen.xyzfunction
data.elements.nitrogen.distributionfunction
data.compound.water.distributionfunction
data.compound.hcl.xyzfunction

したがって、そのような辞書を作成する必要があります

{'data':{'elements':{'hydrogen':{'distributionfunction':<something>}
                     'nitrogen':{'xyzfunction':<something>,
                           'distributionfunction':<something>}
                }
       compound:{'water':{'distributionfunction':<something>}
                 'hcl':{'xyzfunction':<something>}
                }
       }
 }

ディクショナリにどのようにデータを入力するかは、現時点で言うのが難しいデータに依存します。ただし、辞書のキーはヘッダーから入力する必要があり、どういうわけか、データを辞書の空のスロットのそれぞれの値にマップする必要があります。

マップが読み込まれたら、次のようにアクセスできます。

 yourDict['data']['compound']['hcl']['xyzfunction']
于 2011-12-05T17:06:21.203 に答える
3

要素名が動的で、実行時にデータから取得される場合、それらを dict に割り当てて次のようにアクセスできます

elements['hydrogen'].mass

ただし、ドット表記が必要な場合は、実行時に属性を作成できます。

from collections import namedtuple

class Elements(object):
    def add_element(self, elementname, element):
        setattr(self, elementname, element)

Element = namedtuple('Element', ['ux','uy','uz','mass','distributionfunction'])

elements = Elements()
for data in [('hydrogen',1,1,1,1,1), ('helium',2,2,2,2,2), ('carbon',3,3,3,3,3)]:
    elementname = data[0]
    element = Element._make(data[1:])
    elements.add_element(elementname, element)

print elements.hydrogen.mass
print elements.carbon.distributionfunction

ここでは、あなたが持っているデータを想定していますが、他の形式のデータでも同様のトリックを行うことができます

于 2011-12-05T17:09:14.610 に答える
2

ネストされたデータから名前付きタプルを再帰的に作成する方法を次に示します。

from collections import Mapping, namedtuple


def namedtuplify(mapping, name='NT'):  # thank you https://gist.github.com/hangtwenty/5960435
    """ Convert mappings to namedtuples recursively. """
    if isinstance(mapping, Mapping):
        for key, value in list(mapping.items()):
            mapping[key] = namedtuplify(value)
        return namedtuple_wrapper(name, **mapping)
    elif isinstance(mapping, list):
        return [namedtuplify(item) for item in mapping]
    return mapping

def namedtuple_wrapper(name, **kwargs):
    wrap = namedtuple(name, kwargs)
    return wrap(**kwargs)


stuff = {'data': {'elements': {'hydrogen': {'distributionfunction': 'foo'}, 
  'nitrogen': {'xyzfunction': 'bar', 
    'distributionfunction': 'baz'}
  },
  'compound': {'water': {'distributionfunction': 'lorem'}, 
    'hcl': {'xyzfunction': 'ipsum'}}}
 }

example = namedtuplify(stuff)

example.data.elements.hydrogen.distributionfunction  # 'foo'
于 2016-08-31T03:06:30.093 に答える
0

ネストされたjsonでも同じ問題がありましたが、オンザフライでオブジェクトを作成するのが好きではないpickleで出力をシリアル化できる必要がありました。

@bren の回答を参考にして、結果の構造が pickle でシリアル化できるように拡張しました。pickle がそれらを監視できるように、作成した各構造への参照をグローバルに保存する必要があります。

##############################################
class Json2Struct:
    '''
    Convert mappings to nested namedtuples

    Usage:
        jStruct = Json2Struct('JS').json2Struct(json)
    '''
##############################################

    def __init__(self, name):
        self.namePrefix = name
        self.nameSuffix = 0


    def json2Struct(self, jsonObj):  # thank you https://gist.github.com/hangtwenty/5960435
        """ 
        Convert mappings to namedtuples recursively. 
        """
        if isinstance(jsonObj, Mapping):
            for key, value in list(jsonObj.items()):
                jsonObj[key] = self.json2Struct(value)
            return self.namedtuple_wrapper(**jsonObj)
        elif isinstance(jsonObj, list):
            return [self.json2Struct(item) for item in jsonObj]
        return jsonObj


    def namedtuple_wrapper(self, **kwargs):
        self.nameSuffix += 1
        name = self.namePrefix + str(self.nameSuffix)

        Jstruct = namedtuple(name, kwargs)
        globals()[name] = Jstruct

        return Jstruct(**kwargs)

以下の例は、次のように動作し、シリアライズ可能である必要があります。

stuff = {'data': {'elements': {'hydrogen': {'distributionfunction': 'foo'}, 
  'nitrogen': {'xyzfunction': 'bar', 
    'distributionfunction': 'baz'}
  },
  'compound': {'water': {'distributionfunction': 'lorem'}, 
    'hcl': {'xyzfunction': 'ipsum'}}}
 }

example = Json2Struct('JS').json2Struct(stuff)

example.data.elements.hydrogen.distributionfunction  # 'foo'
于 2016-11-17T17:45:51.597 に答える