1

私はアプリケーションを実験してきましたが、この問題があります。以下のようなルールのリストがあります。これは実験データであり、実際のデータにはさらに多くのフィールド(30以上)があります。すべてのレコードには、いくつかの値といくつかの空の値を含めることができます。これはリストのリストですが、defaultdictで保持することもできます(役立つ場合)。約100万件のレコード。

Age  Gender  City    Religion  Propensity
23   *       Delhi   *         0.33
*    M       Mumbai  *         0.78
*    *       *       Hindu     0.23
34   F       Chennai *         0.33
...
...
...

これで、すべての値を持つ1つのデータセット(23、M、デリー、ヒンドゥー)ができました。

上記の表から、次元数の降順で可能な限り速い速度で1つの次元を使用しても、このレコードに一致するすべてのレコードを選択する必要があります。したがって、この場合、行3と1は一致します。したがって、空の値の数が最も少ないレコードが一番下になります。

Python内で大規模に機能する、これを実現するための洗練された方法が必要です。他のソフトウェアは使用できません。

4

4 に答える 4

0

ここにはいくつかの良い答えがあります。私はいくつかのコードを書いてテストしました。

まず、要件の単純な実装を示します。

import pprint

t = [
    [ 23,   None, 'Delhi',   None,    0.33 ],
    [ None, 'M',  'Mumbai',  None,    0.78 ],
    [ None, None,  None,     'Hindu', 0.23 ],
    [ 34,   'F',  'Chennai', None,    0.33 ],
]

rlen = len(t[0])

# None may require special handling
m = [23, 'M', 'Delhi', 'Hindu', None]

a = [[] for i in range(rlen+1)]

for r in t:
    s = sum([1 for i in range(rlen) if r[i] == m[i]])
    if 0 < s:
        a[s].append(r)

# Print rows from least matching to most matching (easy to reverse)
rtable = [row for n in a for row in n]
pprint.pprint(rtable)

問題は、各行をスキャンして各要素の値を確認することです。最後に並べ替える必要がないように、一致する可能性のあるカウントごとに個別のリストを保持してから、リストのリストをフラット化して最終結果を出します。これは、テーブルのサイズに比べて約O(n)のパフォーマンスを期待します。一致する数が多い場合は、さらに悪くなります(大きな結果リストの作成は、O(n)よりも遅くなり、O(n ^ 2)に近づきます。最悪の場合)。

テーブルにインデックスを付けると、処理を高速化できます。列ごとに1つのdictを使用し、セットを使用して列を組み合わせることができます。

from collections import defaultdict
import pprint

# data table
TABLE = [
    [ 23,   None, 'Delhi',   None,    0.33 ],
    [ None, 'M',  'Mumbai',  None,    0.78 ],
    [ None, None,  None,     'Hindu', 0.23 ],
    [ 34,   'F',  'Chennai', None,    0.33 ],
]

# The index is a list of dicts, cdictlist.
# cdictlist is indexed by column number to get the column dict.
# The column dict's key is the data value of the column
def BuildIndex(table):
    rlen = len(table[0])
    rrange = range(rlen)
    cdictlist = [defaultdict(set) for i in range(rlen+1)]
    for ir in range(len(table)):
        r = table[ir]
        for ic in rrange:
            f = r[ic]
            cdictlist[ic][f].add(ir)
    return cdictlist


def multisearch(table, match, cdictlist):
    # rcounts is row counts, number of times columns have matched for a row
    rccounts = defaultdict(int)

    #rset is the result set, set of row indexes returned for this search
    rset = set()

    for ic in range(len(table[0])):
        cset = cdictlist[ic].get(match[ic], set())
        rset = rset.union(cset)
        for i in cset:
            rccounts[i] += 1

    # sort the list by column match count, original row index
    l = sorted((v,k) for (k,v) in rccounts.iteritems())

    # return list of rows, for each row we return (count, index, raw data)
    lr = [ [l[i][0], l[i][1]] + table[l[i][1]] for i in range(len(l)) ]
    return lr

def main():
    cdictlist = BuildIndex(TABLE)

    # None may require special handling
    match = [23, 'M', 'Delhi', 'Hindu', None]

    lr = multisearch(TABLE, match, cdictlist)
    pprint.pprint(lr)

if __name__ == '__main__':
    main()

パフォーマンスは、テーブルのサイズではなく、返されるレコードの数によって異なります。和集合の操作は、多数の一致に対してすぐに問題になります。また、いずれかのフィールドが一致し、フィールドの例の1つがGenderである場合、レコードは一致するため、少なくとも行の半分が返されることを期待する必要があります。

すべての列を一致させる必要がある場合、このアプローチははるかにうまく機能します。返されないレコードのセットを構築し(セットの共通部分を使用)、それらのレコードを除外することで、これを改善できる可能性があります。

于 2012-12-06T15:20:28.200 に答える
0

データを一連の辞書に保存できます。

dict1:age->list<entry>
dict2:gender->list<entry>
...

これで、クエリを取得したら、ヒストグラムを作成し(map:entry-> integer)、値に従って並べ替え、降順で出力するだけです。

実行時間はO(d*m + mlogm)(平均)です。ここdで、はリスト(ディメンション) mの数、は出力エントリの数です。

擬似コード:

assume  list of dictionaries, let it be L:
printRelevants(entry):
   histogram <- new dictionary
   for each dimension d:
      l <- L[d].get(entry[d])
      for each element e in l: #remember to check for null l first
         val <- histogram.get(e)
         if val is null:
             histogram.put(e,1)
         else:
             histogram.put(e,val+1) #assuming overriding old entry with the same key
    #done creating the histogram! 
    sort histogram according to value
    print keys of histogram in descending order
于 2012-12-06T11:56:54.247 に答える
0

「検索条件」が常に同じ、つまり「データセット」(年齢、性別、都市、宗教)が同じであると仮定すると、

「データセット」によってインデックス付けされたリスト(またはセット)の辞書に移動します

result_dict = {}
for record in record_list:
    # you have to know the indexes
    # I'm assuming 0=Age, 1=Gender, 2=City, 3=Hindu
    key_data = []
    for index in [0, 1, 2, 3]:
        key_data.append(str(record[index]))
    key = ','.join(key_data)
    try:
        result_dict[key].append(record)
    except KeyError:
        result_dict[key] = []
        result_dict[key].append(record)

# Find all records that match '23,M,Delhi,Hindu'
print result_dict['23,M,Delhi,Hindu']

しかし、実際には、おそらくデータベースに保存して、SQL クエリを実行するだけです。

于 2012-12-06T12:09:26.940 に答える