2012-11-12 79 views
4

假設我有以下數據框:最佳方式給出的邊緣

a   b 
0 A 1.516733 
1 A 0.035646 
2 A -0.942834 
3 B -0.157334 
4 A 2.226809 
5 A 0.768516 
6 B -0.015162 
7 A 0.710356 
8 A 0.151429 

,我需要它賦予了「邊B」組;這意味着這些組將是:

a   b 
0 A 1.516733 
1 A 0.035646 
2 A -0.942834 
3 B -0.157334 

4 A 2.226809 
5 A 0.768516 
6 B -0.015162 

7 A 0.710356 
8 A 0.151429 

也就是說。任何時候我在列'a'中找到'B'我想分割我的DataFrame。

我目前的解決辦法是:

#create the dataframe 
s = pd.Series(['A','A','A','B','A','A','B','A','A']) 
ss = pd.Series(np.random.randn(9)) 
dff = pd.DataFrame({"a":s,"b":ss}) 

#my solution 
count = 0 
ls = [] 
for i in s: 
    if i=="A": 
     ls.append(count) 
    else: 
     ls.append(count) 
     count+=1 
dff['grpb']=ls 

和我得到的數據框:

a b   grpb 
0 A 1.516733 0 
1 A 0.035646 0 
2 A -0.942834 0 
3 B -0.157334 0 
4 A 2.226809 1 
5 A 0.768516 1 
6 B -0.015162 1 
7 A 0.710356 2 
8 A 0.151429 2 

,我可以再與dff.groupby('grpb')分裂。

有沒有一個更有效的方法來做到這一點使用熊貓功能?

回答

1

另一種方法是:

In [36]: dff 
Out[36]: 
    a   b 
0 A 0.689785 
1 A -0.374623 
2 A 0.517337 
3 B 1.549259 
4 A 0.576892 
5 A -0.833309 
6 B -0.209827 
7 A -0.150917 
8 A -1.296696 

In [37]: dff['grpb'] = np.NaN 

In [38]: breaks = dff[dff.a == 'B'].index 

In [39]: dff['grpb'][breaks] = range(len(breaks)) 

In [40]: dff.fillna(method='bfill').fillna(len(breaks)) 
Out[40]: 
    a   b grpb 
0 A 0.689785  0 
1 A -0.374623  0 
2 A 0.517337  0 
3 B 1.549259  0 
4 A 0.576892  1 
5 A -0.833309  1 
6 B -0.209827  1 
7 A -0.150917  2 
8 A -1.296696  2 

或者用itertools打造 'grpb' 是我的選擇。

2

這裏有一個oneliner:

zip(*dff.groupby(pd.rolling_median((1*(dff['a']=='B')).cumsum(),3,True)))[-1] 

[ 1   2 
0 A 1.516733 
1 A 0.035646 
2 A -0.942834 
3 B -0.157334, 
    1   2 
4 A 2.226809 
5 A 0.768516 
6 B -0.015162, 
    1   2 
7 A 0.710356 
8 A 0.151429] 
2

如何:

df.groupby((df.a == "B").shift(1).fillna(0).cumsum()) 

例如:

>>> df 
    a   b 
0 A -1.957118 
1 A -0.906079 
2 A -0.496355 
3 B 0.552072 
4 A -1.903361 
5 A 1.436268 
6 B 0.391087 
7 A -0.907679 
8 A 1.672897 
>>> gg = list(df.groupby((df.a == "B").shift(1).fillna(0).cumsum())) 
>>> pprint.pprint(gg) 
[(0, 
    a   b 
0 A -1.957118 
1 A -0.906079 
2 A -0.496355 
3 B 0.552072), 
(1, a   b 
4 A -1.903361 
5 A 1.436268 
6 B 0.391087), 
(2, a   b 
7 A -0.907679 
8 A 1.672897)] 

(我沒有理會擺脫指數的;你可以使用[g for k, g in df.groupby(...)]如果你喜歡。)

1
def vGroup(dataFrame, edgeCondition, groupName='autoGroup'): 
    groupNum = 0 
    dataFrame[groupName] = '' 

    #loop over each row 
    for inx, row in dataFrame.iterrows(): 
      if edgeCondition[inx]: 
       dataFrame.ix[inx, groupName] = 'edge' 
       groupNum += 1 
      else: 
       dataFrame.ix[inx, groupName] = groupNum 

    return dataFrame[groupName] 

vGroup(df, df[0] == ' ') 
+0

使用iterrows()循環遍歷每一行;那麼你可以做任何你想做的事情。我認爲這種方法更加靈活。 –