2017-02-17 5 views
3

У меня есть dataframe панды с колонками A и BPython Панды - Капля строка на основе значения

import pandas as pd 
import numpy as np 

df = pd.DataFrame(np.random.randint(0,100,size=(10, 2)), columns=list('AB')) 

я создаю столбец C, который является NULL, если A > B

df['C'] = np.select([ df.A > df.B ], [df.A], default=np.NaN) 

Это дает:

A B  C 
0 95 19 95.0 
1 46 11 46.0 
2 96 86 96.0 
3 22 61 NaN 
4 69 1 69.0 
5 78 91 NaN 
6 42 7 42.0 
7 24 28 NaN 
8 55 92 NaN 
9 92 16 92.0 

Затем я бросаю строки, которые имеют df.C как NaN одним из нескольких способов:

df = df.dropna(subset=['C'], how='any') 

или

df = df.drop(df[pd.isnull(df.C)].index) 

или

df = df.drop(df[(pd.isnull(df.C))].index) 

и все 3 метода дают мне примерно есть строки. В этом случае:

A B  C 
0 95 19 95.0 
1 46 11 46.0 
2 96 86 96.0 
4 69 1 69.0 
6 42 7 42.0 
9 92 16 92.0 

Но когда я не использую номер, например, строка:

df['C'] = np.select([ df.A > df.B ], ['yes'], default=np.NaN) 

Тогда те же 3 методы уронить строки с df.C будучи NaN не фильтруются , Например, когда df.A > df.B устанавливает столбец C в yes, я получаю что-то вроде этого:

A B C 
0 6 70 nan 
1 85 46 yes 
2 76 87 nan 
3 77 36 yes 
4 73 18 yes 
5 1 41 nan 
6 19 69 nan 
7 62 89 nan 
8 6 7 nan 
9 35 75 nan 

я могу это исправить, заменив pd.NaN со строкой, как «ИГНОРИРУЙТЕ», а затем фильтрации «ИГНОРИРУЙТЕ», но Я нахожу этот результат иначе неожиданным.

df['C'] = np.select([ df.A > df.B ], ['yes'], default='IGNORE') 
df = df.drop(df[(df.C == 'IGNORE')].index) 

Что здесь происходит? (Когда df.C строка, мои pd.NaN существа преобразуются в строки?)


Я использую 64-битный Python 2.7.13, панды 0.19.2 и 1.11.3 Numpy на Windows 10.

+0

@Psidom Да, правда. Кажется, NaN буквально «не число» и преобразуется в строку «nan». – philshem

+0

@Psidom, если вы напишете свой комментарий в качестве ответа, я был бы рад принять его. На самом деле это не объясняет почему, но он определенно решает проблему. – philshem

ответ

1

Ваш случай аналогичен к этому:

np.array([1,2,'3',np.nan]) 
# array(['1', '2', '3', 'nan'], 
#  dtype='<U21') 

поскольку np.select также возвращает массив, если вы дополнительно проверить

type(np.nan) 
# float 

str(np.nan) 
# 'nan' 

так np.nan с плавающей точкой, но NumPy массив предпочитает один тип данных для structured array за исключением, поэтому, когда есть строковый элемент в массиве, все элементы преобразуются в строку.


В вашем случае, если у вас есть строка столбец, вы можете использовать None вместо np.nan по умолчанию, это создаст недостающее значение, которое может пройти isnull() проверку и работает с dropna():

import pandas as pd 
import numpy as np 
​ 
df = pd.DataFrame(np.random.randint(0,100,size=(10, 2)), columns=list('AB')) 
df['C'] = np.select([ df.A > df.B ], ['yes'], default=None) 

df.dropna() 

# A B  C 
#0 82 1 yes 
#3 84 8 yes 
#6 52 30 yes 
#7 68 61 yes 
#9 91 87 yes 
2

Вместо того, чтобы бросать, используйте только конечные значения.

df = df[np.isfinite(df['C'])] 

Edit:

Согласно вы прокомментируете nan имеет тип string, поэтому удалите строки на основе значений:

df = df[df.C != "nan"] будет работать

df[df.C.notnull()] 
    A B C 
0 67 23 yes 
1 91 61 yes 
2 30 92 nan 
3 53 97 nan 
4 81 11 yes 
5 23 7 yes 
6 47 39 yes 
7 11 27 nan 
8 46 55 nan 
9 31 82 nan 
df = df[df.C != "nan"] 


    A B C 
0 67 23 yes 
1 91 61 yes 
4 81 11 yes 
5 23 7 yes 
6 47 39 yes 
+0

Я получаю TypeError 'ufunc 'isfinite' не поддерживается для типов ввода, и входы не могут быть безопасно принудительно применены к любым поддерживаемым типам в соответствии с правилом литья ' safe''' – philshem

+0

Я попытался просто имитировать вашу проблему и придумал это решение. import numpy как np import pandas as pd df = pd.DataFrame (np.random.randint (0,100, size = (10, 2)), columns = list ('AB')) df ['C'] = np.select ([df.A> df.B], [df.A], по умолчанию = np.NaN) печати DF ABC 0 81 17 81,0 1 14 67 NaN 2 16 9 16,0 3 25 31 NaN 4 35 36 NaN 5 56 5 56,0 6 18 20 NaN 7 32 4 32,0 46 51 NaN 9 53 34 53,0 DF = DF [np.isfinite (DF [ 'C'])] печати DF ABC 0 81 17 81.0 2 16 9 16,0 5 56 5 56,0 7 32 4 32,0 9 53 34 53,0 –

+0

Хорошо, разница заключается в том, что в моем фактическом коде (а не в примере кода, который я разместил здесь) попробуйте следующее: 'df ['C'] = np. select ([df.A> df.B], [u'yes '], default = np.NaN) ' – philshem

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