Как заменить все записи, отличные от 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)
То же самое можно применить к общему фрейму данных, не определяя имя столбца