2015-04-28 15 views
0

У меня есть DataFrame Pandas с числовыми данными. Для каждого небинарного столбца я хочу определить значения, превышающие его 99-й процентиль, и создать булевскую маску, которую я позже использую для удаления строк с выбросами.Pandas DataFrame применяет функцию удвоения размера DataFrame

Я пытаюсь создать эту булево маску, используя метод apply, где df является DataFrame с числовыми данными размером * б следующим образом.

def make_mask(s): 
    if s.unique().shape[0] == 2: # If binary, return all-false mask 
     return pd.Series(np.zeros(s.shape[0]), dtype=bool) 
    else: # Otherwise, identify outliers 
     return s >= np.percentile(s, 99) 

s_bool = df.apply(make_mask, axis=1) 

К сожалению, s_bool выводится как DataFrame с вдвое большим количеством столбцов (т.е. размер * * 2)). Первые столбцы b имеют имена 1, 2, 3 и т. Д. И заполнены нулевыми значениями. Второй столбец b представляется подходящей маской.

Почему метод apply удваивает размер DataFrame? К сожалению, Pandas apply documentation не предлагает полезные подсказки.

+0

Вы уверены, что вы выложили правильный код? 'raw = True' означает, что функция передается' ndarray', а объекты 'ndarray' не имеют уникального метода. Я попробовал его с 'raw = False', и он работал нормально. – TheBlackCat

+0

Неплохо, аргумент 'raw' не должен указываться так, чтобы он был установлен как' False' неявно. Удвоение столбцов происходит, когда я вообще не устанавливаю этот аргумент. –

+0

Я попробовал новую версию со случайным DataFrame и не смог воспроизвести проблему: 'df = pd.DataFrame (np.random.random ((50,20)), columns = tuple ('abcdefghijklmnopqrstuvwxyz' [: 20]) , index = np.arange (0,5, .1)) ' – TheBlackCat

ответ

1

Я не понимаю, почему, но, похоже, проблема в том, что вы возвращаете серию. Это похоже на работу в вашем данном примере:

def make_mask(s): 
    if s.unique().shape[0] == 2: # If binary, return all-false mask 
     return np.zeros(s.shape[0], dtype=bool) 
    else: # Otherwise, identify outliers 
     return s >= np.percentile(s, 99) 

Вы можете еще больше упростить код, как это так, и использовать raw=True:

def make_mask(s): 
    if np.unique(s).size == 2: # If binary, return all-false mask 
     return np.zeros_like(s, dtype=bool) 
    else: # Otherwise, identify outliers 
     return s >= np.percentile(s, 99) 
+0

Это также решает проблему с моими исходными данными. Спасибо! –