2017-02-08 5 views
3

Я знаю, как отбросить строку из DataFrame, содержащей все значения NULL или один null, но вы можете удалить строку на основе нулей для указанного набора столбцов?Удалить строку на основе нулей в определенных столбцах (pandas)

Например, я использую данные, содержащие географическую информацию (город, широту и долготу), а также множество других полей. Я хочу сохранить строки, которые, как минимум, содержат значение для города OR для lat и long, но отбрасывают строки, которые имеют нулевые значения для всех трех.

У меня возникли проблемы с поиском функций для этого в документации pandas. Любые рекомендации будут оценены.

+0

Мат, это в документации. Проверьте справку по функции [dropna] (http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.dropna.html) –

+0

@GeneBurinsky, no, 'dropna()' будет работать некорректно в этом случае. Проверьте строку с индексом '4' в моем примере. 'df.dropna (subset = ['city', 'latitude', 'longitude'], how = 'all')' отбросит его ... – MaxU

+1

@MaxU, это справедливая точка. Однако, по крайней мере для вашего примера, это будет работать 'df.dropna (axis = 0, subset = [['city', 'longitude', 'latitude']], thresh = 2)', но в целом вы правильные, явные логические утверждения для желаемого превосходят решение 'dropna' –

ответ

2

Попробуйте это:

In [25]: df 
Out[25]: 
    city latitude longitude a b 
0 aaa 11.1111  NaN 1 2 
1 bbb  NaN 22.2222 5 6 
2 NaN  NaN  NaN 3 4 
3 NaN 11.1111 33.3330 1 2 
4 NaN  NaN 44.4440 1 1 

In [26]: df.query("city == city or (latitude == latitude and longitude == longitude)") 
Out[26]: 
    city latitude longitude a b 
0 aaa 11.1111  NaN 1 2 
1 bbb  NaN 22.2222 5 6 
3 NaN 11.1111 33.3330 1 2 

Если я понимаю правильно ОП строка с индексом 4 должны быть отброшены, как не обе координаты не-нуль. Так dropna() не будет работать «правильно» в данном случае:

In [62]: df.dropna(subset=['city','latitude','longitude'], how='all') 
Out[62]: 
    city latitude longitude a b 
0 aaa 11.1111  NaN 1 2 
1 bbb  NaN 22.2222 5 6 
3 NaN 11.1111 33.3330 1 2 
4 NaN  NaN 44.4440 1 1 # this row should be dropped... 
+0

Правильно, индекс 4 нужно будет отбросить. Кажется, это то, что я искал. Я не знал, что вы можете использовать booleans таким образом для query(). Благодаря! – gesingle

2

dropna имеет параметр, чтобы применить тесты только на подмножестве столбцов:

dropna(axis=0, how='all', subset=[your three columns in this list]) 
+0

Обратите внимание, что, как указано в комментариях к MaxU, это не совсем сработало бы на примере тестового набора. –

0

Вы можете выполнить выбор, используя побитовое операторы.

## create example data 
df = pd.DataFrame({'City': ['Gothenburg', None, None], 'Long': [None, 1, 1], 'Lat': [1, None, 1]}) 

## bitwise/logical operators 
~df.City.isnull() | (~df.Lat.isnull() & ~df.Long.isnull()) 
0  True 
1 False 
2  True 
dtype: bool 

## subset using above statement 
df[~df.City.isnull() | (~df.Lat.isnull() & ~df.Long.isnull())] 
     City Lat Long 
0 Gothenburg 1.0 NaN 
2  None 1.0 1.0 
2

Вы можете использовать pd.dropna, но вместо того, чтобы использовать how='all' и subset=[], вы можете использовать параметр thresh требовать минимального количества ВПЛ подряд, прежде чем строка потеряется. В городе, длинном/латском примере, thresh=2 будет работать, потому что мы просто бросаем в случае 3 NA. Используя пример больших данных, созданный с помощью MaxU, мы бы

## get the data 
df = pd.read_clipboard() 

## remove undesired rows 
df.dropna(axis=0, subset=[['city', 'longitude', 'latitude']], thresh=2) 

Это дает:

In [5]: df.dropna(axis=0, subset=[['city', 'longitude', 'latitude']], thresh=2) 
Out[5]: 
    city latitude longitude a b 
0 aaa 11.1111  NaN 1 2 
1 bbb  NaN 22.2222 5 6 
3 NaN 11.1111 33.3330 1 2 
+0

Спасибо! Четкое и сжатое решение. – gesingle

1

Использования булевой маски и некоторому умным dot продукта (это для @Boud)

subset = ['city', 'latitude', 'longitude'] 
df[df[subset].notnull().dot([2, 1, 1]).ge(2)] 

    city latitude longitude a b 
0 aaa 11.1111  NaN 1 2 
1 bbb  NaN 22.2222 5 6 
3 NaN 11.1111 33.3330 1 2 
Смежные вопросы