2016-11-23 15 views
3

私は'B'効率的な方法

df.groupby('A').B.union()df.groupby('A').B.apply(set.union)どちらも仕事で'A'と組合すべてのリストでグループ化するこのdf

df = pd.DataFrame(dict(
     A=['b', 'a', 'b', 'c', 'a', 'c', 'a', 'c', 'a', 'a'], 
     B=[[0, 2, 3, 1], 
      [9, 6, 7, 2], 
      [6, 0, 1, 4], 
      [9, 2, 5, 1], 
      [5, 1, 4, 8], 
      [8, 5, 6, 6], 
      [0, 9, 0, 0], 
      [2, 6, 1, 8], 
      [7, 3, 2, 6], 
      [8, 7, 1, 9]] 
     )) 

を持っています。

私は、問題は、あなたが労働組合を適用する前に最初のセットとしてそれらをキャストする必要があるということです

def f(x): 
    # grabbing first one so I can 
    # make a set out of it 
    first, *rest = x.values.tolist() 
    # union won't work unless it's on 
    # a set, it doesn't care about the rest 
    return set(first).union(*rest) 

df.groupby('A').B.apply(f) 

A 
a {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} 
b    {0, 1, 2, 3, 4, 6} 
c    {1, 2, 5, 6, 8, 9} 
Name: B, dtype: object 

答えて

5

に適用するための機能を使用したい結果が

A 
a {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} 
b    {0, 1, 2, 3, 4, 6} 
c    {1, 2, 5, 6, 8, 9} 
Name: B, dtype: object 
+5

第二 'map'が必要ですか?それなしで私のためにうまく動作します。 – root

+0

ええ、セット工事は十分でなければなりません、あなたはちょうど一組の組を最後に取っています。 –

+0

非常にエレガントなソリューション! – MaxU

1

になりたいです。一つの解決策はmap

In [28]: df.groupby('A').B.sum().map(set) 
Out[28]: 
A 
a {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} 
b    {0, 1, 2, 3, 4, 6} 
c    {1, 2, 5, 6, 8, 9} 
dtype: object 
2

maxymooの答えはいいですが、それは最初に一緒にすべてのリストが追加されますので、それが不必要に特にそう(大量のメモリがかかる場合があります使用して設定するキャスト、その後、グループを連結するsumを使用することです重複が多い場合)。

代わりに、最初に列Bをセットに変換してから、後で1つのセットにさらに効率的に減らすことができます。このように:ワンライナーとして

df['B'] = df['B'].map(set) 

    A    B 
0 b {0, 1, 2, 3} 
1 a {9, 2, 6, 7} 
2 b {0, 1, 4, 6} 
3 c {9, 2, 5, 1} 
4 a {8, 1, 4, 5} 
5 c  {8, 5, 6} 
6 a  {0, 9} 
7 c {8, 1, 2, 6} 
8 a {2, 3, 6, 7} 
9 a {8, 1, 9, 7} 

df.groupby('A').B.apply(lambda x: reduce(set.union, x)) 

A 
a {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} 
b    {0, 1, 2, 3, 4, 6} 
c    {1, 2, 5, 6, 8, 9} 
Name: B, dtype: object 

または、maxymooが指摘するように:

df.groupby('A').B.apply(lambda x : reduce(set.union, x.map(set))) 
+0

yehこれは私の答えよりも優れています – maxymoo

+1

実際に1ライナーが必要な場合は、 'df.groupby( 'A')を使うことができます。 (λx:reduce(set.union、x.map(set))) 'を返し、ラムダ – maxymoo

+0

にデータ型変換を含めると、実際には' df.groupby( 'A' 'union'の最初の引数だけがセットである必要があるというHarryの答えの見解を使って、reduce(set.union、x、set(x.iloc [0])))' – maxymoo