2017-09-28 36 views
1

我需要选择行数大于mac列中项目的计数(即1)的行。 然后用时间戳的最小值和最大值创建一个DataFrame。在python中选择带有熊猫数据框的布尔数组的行

a=np.array([['A',1],['A',2],['A',3],['B',2],['C',1],['C',2]]) 
df=pd.DataFrame(a,columns=['mac','timestamp']) 
df 
Out[103]: 
    mac timestamp 
0 A   1 
1 A   2 
2 A   3 
3 B   2 
4 C   1 
5 C   2 

count_macs= df.groupby(['mac'])['mac'].count()>1 
count_macs 
Out[105]: 
mac 
A  True 
B False 
C  True 
Name: mac, dtype: bool 

我想获得:

mac  ts1  ts2 
A  1  3 
C  1  2 

但不知道如何正确适用的.loc:

df.loc[count_macs] 
IndexingError: Unalignable boolean Series key provided 

回答

2

lambda

f = lambda g: g.timestamp.agg(['min', 'max'])[g.size() > 1] 
h = lambda x, c=iter(['ts1', 'ts2']): next(c) 
f(df.groupby('mac')).rename(columns=h).reset_index() 

    mac ts1 ts2 
0 A 1 3 
1 C 1 2 

只是为了享受乐趣要清楚:我们可以放弃h一个ð只是做

f = lambda g: g.timestamp.agg(['min', 'max'])[g.size() > 1] 
f(df.groupby('mac')).rename(columns=dict(min='ts1', max='ts2')).reset_index() 

    mac ts1 ts2 
0 A 1 3 
1 C 1 2 

但我喜欢用h( - :

+0

先生你爱上拉姆达? :) :) – Dark

+1

否( - :我在一行中写了这个,我想把df.groupby('mac')'传递给'lambda'以便使用两次,但是计算一次。 ,我想重新命名内联列,我决定使用将迭代器传递给lambda的概念......嗯,我最终得到了上面的答案 – piRSquared

+0

f是完美的,我通过一个groupby和它使用了两次,非常简单,非常优雅,'h'是为了好玩,可以像你的字典'd'一样容易。 – piRSquared

2

我认为你需要aggmaxminsize (或者count如果不需要计数NaN s)。然后,通过boolean indexing过滤,除去一列和最后重新命名列:

df = df.groupby('mac')['timestamp'].agg(['min','max', 'size']) 
d = {'min':'t1','max':'t2'} 
df = df[df['size'] > 1].drop('size', 1).rename(columns=d).reset_index() 
#alternatively: 
#df = df.query('size > 1').drop('size', 1).rename(columns=d).reset_index() 

print (df) 
    mac t1 t2 
0 A 1 3 
1 C 1 2 

另一种解决方案是过滤器先用duplicated

df = df[df['mac'].duplicated(keep=False)] 
d = {'min':'t1','max':'t2'} 
df = df.groupby('mac')['timestamp'].agg(['min','max']).rename(columns=d).reset_index() 
print (df) 
    mac t1 t2 
0 A 1 3 
1 C 1 2