2016-07-06 8 views
4

リストのリストがあります。各サブリストの長さは1〜100の間です。各サブリストには、データセット内の異なる時間にパーティクルIDが含まれています。ある時点ですべてのパーティクルIDのリストを作成したいと思います。リスト内の各サブリストの最初の要素が含まれます異なる長さのサブリストのスライシング

list = [[1,2,3,4,5],[2,6,7,8],[1,3,6,7,8]] 
    list2 = [item[0] for item in list] 

LIST2:これを行うには、私のようなものを使用することができます。最初の要素だけでなく、1から100までのすべての要素に対してこの操作を行いたいと思います。私の問題は、要素番号100(または66または77など)がすべてのサブリストに存在しないことです。

リストのリストを作成する方法はありますか。各サブリストは、特定の時点のすべてのパーティクルIDのリストです。

この問題を解決するためにnumpy配列を使用しようと考えました。リストがすべて同じ長さであるように、これは簡単です。私は各リストの末尾に-1を加えて同じ長さにしてから、負の数をマスキングすることを試みましたが、これは今まで私にとってはうまくいきませんでした。あなたはone-line forloopとし、arrayでそれをしたい場合は

pos = pos[satIDs] 
+0

これを1行のループで行いますか?または任意のforループが行うでしょうか? – Navid777

+0

ループは実行されますが、データセットはかなり大きいので、速度が問題になる可能性があります。 – Jack

+0

"負の数をマスキングしていますが、これはこれまでのところ私にとってはうまくいきませんでした" - どうしてそれがうまくいかなかったのですか? – Divakar

答えて

2
lst = [[1,2,3,4,5],[2,6,7,8],[1,3,6,7,8]] 
func = lambda x: [line[x] for line in lst if len(line) > x] 

func(3) 
[4, 8, 7] 
func(4) 
[5, 8] 

--update--

func = lambda x: [ (line[x],i) for i,line in enumerate(lst) if len(line) > x] 
func(4) 
[(5, 0), (8, 2)] 
+0

ありがとう、func(x)のどの要素がどのリストから来たのかを追跡する方法もあります。 (func(4)の場合)5がサブリスト0から来て8がサブリスト2から来たという追加のリスト? – Jack

+0

... 'ラムダ 'を使って名前に割り当てるのは何ですか?単に 'def func(x):return [line [x] ...]'を使ってください。 – Bakuriu

+0

@Jackが更新されました。タプルの最初の要素は値で、2番目はサブリストの番号です – galaxyan

0

:私は別の独立した配列をスライスするために与えられた時間にIDのリストを使用します。あなたはこれを行うことができます:

list2 = [[item[i] for item in list if len(item) > i] for i in range(0, 100)] 

そして、あなたがこれを行うことができるリストからどのIDであるか知りたい場合:

list2 = [{list.index(item): item[i] for item in list if len(item) > i} for i in range(0, 100)] 

リスト2はこのようになります:

[{0: 1, 1: 2, 2: 1}, {0: 2, 1: 6, 2: 3}, {0: 3, 1: 7, 2: 6}, {0: 4, 1: 8, 2: 7}, 
{0: 5, 2: 8}, {}, {}, ... ] 
0

あなたの短いリストにnumpy.nanを追加し、その後numpyの配列あなたはいつものようにnumpyのスライスを使用することができます。その後

import numpy 
import itertools 

lst = [[1,2,3,4,5],[2,6,7,8],[1,3,6,7,8,9]] 
arr = numpy.array(list(itertools.izip_longest(*lst, fillvalue=numpy.nan))) 

を作成することができます。

print arr 
print arr[1, :] # [2, 6, 3] 
print arr[4, :] # [5, nan, 8] 
print arr[5, :] # [nan, nan, 9] 
+0

この方法でスライスを実行した場合、スライスされた配列の各要素がどの行から来たのかを知ることができますか?私。それはナンを保つだろうか? – Jack

+0

はい、もちろんです。エントリが「ナノ」になるリストの最後を過ぎて実行するときはいつでも。 –

+0

しかし、スライス配列を使うことができます。例えば、x = [nan、nan、9]とすると、別の配列のスライスを実行します。data [x] - これはエラーになりませんか? IndexError:インデックスとして使用される配列は整数(またはブール型)でなければなりません – Jack

0

itertools.zip_longestを使用できます。リストの1つが使い果たされると、zipリストが一緒になり、Noneが挿入されます。

>>> lst = [[1,2,3,4,5],['A','B','C'],['a','b','c','d','e','f','g']]  
>>> list(itertools.zip_longest(*lst)) 
[(1, 'A', 'a'), 
(2, 'B', 'b'), 
(3, 'C', 'c'), 
(4, None, 'd'), 
(5, None, 'e'), 
(None, None, 'f'), 
(None, None, 'g')] 

あなたがそれらをフィルタリングすることができ、None要素を必要としない場合:

>>> [[x for x in sublist if x is not None] for sublist in itertools.zip_longest(*lst)] 
[[1, 'A', 'a'], [2, 'B', 'b'], [3, 'C', 'c'], [4, 'd'], [5, 'e'], ['f'], ['g']] 
0

アプローチ#1

ワンほとんど*ベクトル化されたアプローチは、それが一緒に行く提案することができ新しい注文に基づいてIDを作成し、分割するように -

def position_based_slice(L): 

    # Get lengths of each element in input list 
    lens = np.array([len(item) for item in L]) 

    # Form ID array that has *ramping* IDs within an element starting from 0 
    # and restarts with a new element at 0 
    id_arr = np.ones(lens.sum(),int) 
    id_arr[lens[:-1].cumsum()] = -lens[:-1]+1 

    # Get order maintained sorted indices for sorting flattened version of list 
    ids = np.argsort(id_arr.cumsum(),kind='mergesort') 

    # Get sorted version and split at boundaries decided by lengths of ids 
    vals = np.take(np.concatenate(L),ids) 
    cut_idx = np.where(np.diff(ids)<0)[0]+1 
    return np.split(vals,cut_idx) 

*開始時にはループの理解が含まれていますが、リストの入力要素の長さだけを収集することを意図しているため、ランタイム全体への影響は最小限に抑える必要があります。

サンプル実行 -

In [76]: input_list = [[1,2,3,4,5],[2,6,7,8],[1,3,6,7,8],[3,2]] 

In [77]: position_based_slice(input_list) 
Out[77]: 
[array([1, 2, 1, 3]), # input_list[ID=0] 
array([2, 6, 3, 2]), # input_list[ID=1] 
array([3, 7, 6]), # input_list[ID=2] 
array([4, 8, 7]), # input_list[ID=3] 
array([5, 8])]  # input_list[ID=4] 

アプローチ#2

はここで、インデックスに簡単で、オリジナルの入力要素に遡る2D配列を作成し、別のアプローチです。これは、ブールインデックス付けと一緒にNumPyブロードキャストを使用します。

def position_based_slice_2Dgrid(L): 

    # Get lengths of each element in input list 
    lens = np.array([len(item) for item in L]) 

    # Create a mask of valid places in a 2D grid mapped version of list 
    mask = lens[:,None] > np.arange(lens.max()) 
    out = np.full(mask.shape,-1,dtype=int) 
    out[mask] = np.concatenate(L) 
    return out 

サンプル実行 - - 実装がこのようなものになりますので

In [126]: input_list = [[1,2,3,4,5],[2,6,7,8],[1,3,6,7,8],[3,2]] 

In [127]: position_based_slice_2Dgrid(input_list) 
Out[127]: 
array([[ 1, 2, 3, 4, 5], 
     [ 2, 6, 7, 8, -1], 
     [ 1, 3, 6, 7, 8], 
     [ 3, 2, -1, -1, -1]]) 

を、今出力の各列には、IDベースの出力に対応することになります。

関連する問題