我有以下pandas数据帧。
import pandas as pd
# Initialize dataframe
df1 = pd.DataFrame(columns=['bar', 'foo'])
df1['bar'] = ['001', '001', '001', '001', '002', '002', '003', '003', '003']
df1['foo'] = [-4, -3, 2, 3, -3, -2, 0, 1, 2]
>>> print df1
bar foo
0 001 -4
1 001 -3
2 001 2
3 001 3
4 002 -3
5 002 -2
6 003 0
7 003 1
8 003 2
考虑以下阈值和参数。
# Provide threshold and number of entries above and below threshold
threshold = 0
n_below = 2
n_above = 2
我想创建一个过滤掉bar
的某些值的数据框。我想要过滤掉的bar
如下:如果n_below
的值foo
的{{1}}值小于threshold
且值n_above
大于foo
的{{1}}。
对于上面的例子:
threshold
不会被过滤掉,因为对于bar = 001
,至少有bar = 001
条n_below = 2
小于foo
且至少threshold = 0
条{1}} n_above = 2
大于foo
的条目。 threshold = 0
将被过滤掉,因为对于bar = 002
,bar = 002
个n_above = 2
个条目至少不超过foo
。 threshold = 0
将被过滤掉,因为对于bar = 003
,至少有bar = 003
条n_below = 2
小于foo
。 所需的输出如下:
threshold = 0
我相信这可以通过GroupBy和# Desired output
bar foo
0 001 -4
1 001 -3
2 001 2
3 001 3
完成,但是我无法获得有效的解决方案。我认识到编写一个可以分两步完成此操作的解决方案可能更清晰:1)首先满足.count()
条件的过滤器; 2)然后过滤以满足n_below
条件。
答案 0 :(得分:3)
您可以使用groupby
和filter
方法。
threshold = 0
n_below = 2
n_above = 2
def filter_function(g):
'''Called by filter, g is the grouped dataframe'''
l = g['foo']
return (sum([x < threshold for x in l]) >= n_below
and sum([x > threshold for x in l]) >= n_above)
df.groupby('bar').filter(filter_function)
# gives
bar foo
0 1 -4
1 1 -3
2 1 2
3 1 3
答案 1 :(得分:2)
我认为有一个解决方案:
threshold = 1
n_below = 2
n_above = 2
df1.set_index('bar').loc[ \
df1.groupby('bar')\
.apply(lambda df_sub: \
(df_sub['foo']<threshold).sum()>=n_below \
and (df_sub['foo']>threshold).sum()>=n_above)] \
.reset_index('bar')
然后返回
bar foo
0 001 -4
1 001 -3
2 001 2
3 001 3
答案 2 :(得分:1)
idx = df1.groupby('bar').apply(lambda x: (sum(x['foo'] < threshold) >= n_below) & (sum(x['foo'] > threshold) >= n_above))
print df1.set_index('bar')[idx].reset_index()
bar foo
0 001 -4
1 001 -3
2 001 2
3 001 3