2013-11-26 5 views
14

У меня есть dataframe, который может иметь или не иметь столбцы, которые имеют одинаковое значение. Напримерpanda dataframe удалить постоянный столбец

row A B 
    1  9 0 
    2  7 0 
    3  5 0 
    4  2 0 

Я хотел бы вернуться только

row A 
    1  9  
    2  7  
    3  5  
    4  2 

Есть простой способ определить, если какой-либо из этих столбцов существуют, а затем удалить их?

ответ

20

Я считаю, что этот вариант будет быстрее, чем другие ответы здесь, как это будет проходить фрейм данных только один раз для сравнения и короткого замыкания, если неоднозначный значение найдено.

>>> df 

    0 1 2 
0 1 9 0 
1 2 7 0 
2 3 7 0 

>>> df.loc[:, (df != df.iloc[0]).any()] 

    0 1 
0 1 9 
1 2 7 
2 3 7 
+2

Aargh to: '<>'. –

+0

@ AndyHayden Паскаль привычки умереть. Я изменил его. – chthonicdaemon

+0

+1 спасибо за изменение. Это короткие замыкания на любом, после того, как это уже сделано! = Сравнение по каждому элементу, поэтому решение DSM, вероятно, будет более эффективным ... задайтесь вопросом, лучше ли это решение с коротким замыканием. –

13

Игнорирование NaN s как обычно, столбец постоянный, если nunique() == 1. Итак:

>>> df 
    A B row 
0 9 0 1 
1 7 0 2 
2 5 0 3 
3 2 0 4 
>>> df = df.loc[:,df.apply(pd.Series.nunique) != 1] 
>>> df 
    A row 
0 9 1 
1 7 2 
2 5 3 
3 2 4 
+0

'df.apply (pd.Series.nunique)' более просто 'df.nunique()', по крайней мере, в Pandas 0.20.3. – EOL

+0

И если мы хотим, чтобы NaN считалось уникальным значением, 'df.nunique (dropna = False)' работает хорошо (он обрабатывает тот факт, что NaN ≠ NaN, как мы ожидаем, считая все значения NaN одинаковым значением, даже если они не равны). – EOL

2

Предполагая, что DataFrame полностью типа числового:

вы можете попробовать:

>>> df = df.loc[:, df.var() == 0.0] 

, который будет удалять столбцы постоянной (т.е. дисперсии = 0.).

Если DataFrame имеет тип как числовой и объекта, то вы должны попробовать:

>>> enum_df = df.select_dtypes(include=['object']) 
>>> num_df = df.select_dtypes(exclude=['object']) 
>>> num_df = num_df.loc[:, num_df.var() == 0.0] 
>>> df = pd.concat([num_df, enum_df], axis=1) 

, которые будут падать постоянные столбцы только числового типа.

Если вы хотите игнорировать/удалить постоянные столбцы перечислений, вы должны попробовать:

>>> enum_df = df.select_dtypes(include=['object']) 
>>> num_df = df.select_dtypes(exclude=['object']) 
>>> enum_df = enum_df.loc[:, [True if y !=1 else False for y in [len(np.unique(x, return_counts=True)[-1]) for x in enum_df.T.as_matrix()]]] 
>>> num_df = num_df.loc[:, num_df.var() == 0.0] 
>>> df = pd.concat([num_df, enum_df], axis=1) 
+0

Предположительно, вам нужно будет 'df = df.loc [:, ~ df.var() == 0.0]' в противном случае вы выбираете столбцы 0. Вероятно, также стоит сделать 'np.isclose (0, df.var())' для возможных ошибок с плавающей запятой – jeremycg

0

Вот мое решение, так как мне нужно было сделать как объект и числовые столбцы. Не заявляя, что он суперэффективен или что-то еще, но он выполняет свою работу.

def drop_constants(df): 
    """iterate through columns and remove columns with constant values (all same)""" 
    columns = df.columns.values 
    for col in columns: 
     # drop col if unique values is 1 
     if df[col].nunique(dropna=False) == 1: 
      del df[col] 
    return df 

Дополнительное предупреждение, оно не будет работать на столбцах списков или массивов, поскольку они не являются хешируемыми.

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