2016-10-16 3 views
2

У меня есть кадр данных, который представляет разные классы с их значениями. например:Изменение значения групп с несколькими членами в кадре данных pandas

df=pd.DataFrame(
{'label':['a','a','b','a','b','b','a','c','c','d','e','c'], 
'date':[1,2,3,4,3,7,12,18,11,2,5,3],'value':np.random.randn(12)}) 

Я хочу выбрать ярлыки с values_counts меньше определенного порога, а затем поместить их в один класс т.е. маркировать их как, например, «ноль».

Это мой attemp:

value_count=df.label.value_counts() 
threshold = 3 
for index in value_count[value_count.values<=threshold].index: 
    df.label[df.label==index]='zero' 

Есть ли лучший способ сделать это?

ответ

2

Вы можете использовать groupby.transform, чтобы получить отсчеты значений, выровненные с исходным индексом, а затем использовать его в качестве булевой индекс:

df.loc[df.groupby('label')['label'].transform('count') <= threshold, 'label'] = 'zero' 

df 
Out: 
    date label  value 
0  1  a -0.587957 
1  2  a 0.341551 
2  3 zero 0.516933 
3  4  a 0.234042 
4  3 zero -0.206185 
5  7 zero 0.840724 
6  12  a -0.728868 
7  18 zero 0.111260 
8  11 zero -0.471337 
9  2 zero 0.030803 
10  5 zero 1.012638 
11  3 zero -1.233750 

Вот мои тайминги:

df = pd.concat([df]*10**4) 

%timeit df.groupby('label')['label'].transform('count') <= threshold 
100 loops, best of 3: 7.86 ms per loop 

%%timeit 
value_count=df.label.value_counts() 
df['label'].isin(value_count[value_count.values<=threshold].index) 
100 loops, best of 3: 9.24 ms per loop 
+0

Умм, я обновил контрольные показатели, мои противоположны. Однако мне нравится ваше решение. :-) – Zero

+0

@JohnGalt, не забудьте «timeit»: 'value_count = df.label.value_counts()';) – MaxU

+0

Да, это имеет смысл сейчас. Благодарю. – Zero

1

Вы могли бы сделать

In [59]: df.loc[df['label'].isin(value_count[value_count.values<=threshold].index), 
'label'] = 'zero' 

In [60]: df 
Out[60]: 
    date label  value 
0  1  a -0.132887 
1  2  a -1.306601 
2  3 zero -1.431952 
3  4  a 0.928743 
4  3 zero 0.278955 
5  7 zero 0.128430 
6  12  a 0.200825 
7  18 zero -0.560548 
8  11 zero -2.925706 
9  2 zero -0.061373 
10  5 zero -0.632036 
11  3 zero -1.061894 

Timings

In [87]: df = pd.concat([df]*10**4, ignore_index=True) 

In [88]: %timeit df['label'].isin(value_count[value_count.values<=threshold].index) 
100 loops, best of 3: 7.1 ms per loop 

In [89]: %timeit df.groupby('label')['label'].transform('count') <= threshold 
100 loops, best of 3: 11.7 ms per loop 

In [90]: df.shape 
Out[90]: (120000, 3) 

Возможно, вы захотите сравнить с большим набором данных. И это может быть неточным для сравнения, так как вы предварительно комментируете value_count

Смежные вопросы