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').

有没有更有效的方法可以使用 pandas 函数来做到这一点?

4

4 回答 4

2

这是一个单线:

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]
于 2013-03-16T13:43:42.183 回答
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(...)]如果您愿意,可以使用。)

于 2013-03-16T14:28:43.240 回答
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] == '  ')
于 2013-04-28T01:23:29.110 回答
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' 也是一种选择。

于 2012-11-13T09:21:03.657 回答