Как заменить все записи, отличные от NaN, на единицу данных с 1 и все NaN с помощью 0

У меня есть dataframe с 71 столбцом и 30597 строками. Я хочу заменить все не-нанные записи на 1 и нан с помощью 0.

Изначально я пробовал for-loop на каждое значение кадра данных, которое занимало слишком много времени.

Затем я использовал data_new = data.subtract(data), который предназначался для вычитания всех значений фрейма данных для себя, чтобы я мог сделать все ненулевые значения 0. Но произошла ошибка, так как в dataframe было несколько записей строк.

Ответ 1

Вы можете взять возвращаемое значение df.notnull(), которое равно False, где DataFrame содержит NaN и True в противном случае и отбрасывает его на целое число, предоставляя вам 0, где DataFrame NaN и 1 в противном случае:

newdf = df.notnull().astype('int')

Если вы действительно хотите записать в свой исходный DataFrame, это будет работать:

df.loc[~df.isnull()] = 1  # not nan
df.loc[df.isnull()] = 0   # nan

Ответ 2

Используйте notnull с литьем boolean на int astype:

print ((df.notnull()).astype('int'))

Пример:

import pandas as pd
import numpy as np

df = pd.DataFrame({'a': [np.nan, 4, np.nan], 'b': [1,np.nan,3]})
print (df)
     a    b
0  NaN  1.0
1  4.0  NaN
2  NaN  3.0

print (df.notnull())
       a      b
0  False   True
1   True  False
2  False   True

print ((df.notnull()).astype('int'))
   a  b
0  0  1
1  1  0
2  0  1

Ответ 3

В DataFrames существует метод .fillna(), который делает то, что вам нужно. Например:

df = df.fillna(0)  # Replace all NaN values with zero, returning the modified DataFrame

или

df.fillna(0, inplace=True)   # Replace all NaN values with zero, updating the DataFrame directly

Ответ 4

Я делаю много анализа данных и заинтересован в поиске новых/более быстрых методов проведения операций. Я никогда не сталкивался с методом jezrael, поэтому мне было любопытно сравнить его с моим обычным методом (т.е. Заменить индексированием). ПРИМЕЧАНИЕ. Это не ответ на вопрос ОП, а скорее иллюстрация эффективности jezrael метода. Поскольку это НЕ ответ, я удалю этот пост, если люди не сочтут это полезным (и после того, как он будет забыт!). Просто оставьте комментарий, если вы думаете, что я должен его удалить.

Я создал модельный ряд с умеренным размером и сделал несколько замен, используя метод df.notnull(). astype (int) и простое индексирование (как обычно я это делаю). Оказывается, последнее медленнее примерно в пять раз. Просто fyi для тех, кто делает более крупные замены.

from __future__ import division, print_function

import numpy as np
import pandas as pd
import datetime as dt


# create dataframe with randomly place NaN's
data = np.ones( (1e2,1e2) )
data.ravel()[np.random.choice(data.size,data.size/10,replace=False)] = np.nan

df = pd.DataFrame(data=data)

trials = np.arange(100)


d1 = dt.datetime.now()

for r in trials:
    new_df = df.notnull().astype(int)

print( (dt.datetime.now()-d1).total_seconds()/trials.size )


# create a dummy copy of df.  I use a dummy copy here to prevent biasing the 
# time trial with dataframe copies/creations within the upcoming loop
df_dummy = df.copy()

d1 = dt.datetime.now()

for r in trials:
    df_dummy[df.isnull()] = 0
    df_dummy[df.isnull()==False] = 1

print( (dt.datetime.now()-d1).total_seconds()/trials.size )

Это дает время 0,142 с и 0,685 с соответственно. Понятно, кто победитель.

Ответ 5

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

например. если df ['col1'] - это существующий столбец

df['col2'] = df['col1'].apply(lambda x: 1 if not pd.isnull(x) else np.nan)

где col2 - новый столбец. Должен также работать, если col2 имеет записи строк.

Ответ 6

Использование: df.fillna(0)

чтобы заполнить NaN 0.

Ответ 7

Здесь я дам предложение взять конкретный столбец, и если строки в этом столбце имеют значение NaN, заменить его на 0 или значения в этом столбце заменить его на 1

эта строка изменит ваш столбец на 0

df.YourColumnName.fillna(0,inplace=True)

Теперь часть Not Nan будет заменена на 1 кодом ниже

dfff["PlayDescription"]=dfff["PlayDescription"].apply(lambda x: 1 if x!=0 else 0)

То же самое можно применить к общему фрейму данных, не определяя имя столбца