Назначение контейнеров в Пандах
Я хочу заменить None
Записи в определенном столбце в Пандах с пустым списком.
Обратите внимание, что некоторые записи в этом столбце уже могут содержать пустой список, и я не хочу их трогать.
Я пытался:
indices = np.equal(df[col],None)
df[col][indices] = []
а также
indices = np.equal(df[col],None)
df[col][indices] = list()
но оба решения терпят неудачу с:
ValueError: Length of replacements must equal series length
Зачем? Как я могу обновить эти конкретные строки с пустым списком?
2 ответа
Использование эндемичных списков не допускается при назначении и не рекомендуется делать это вообще.
Вы можете сделать это, если вы создаете с нуля
In [50]: DataFrame({ 'A' : [[],[],1]})
Out[50]:
A
0 []
1 []
2 1
[3 rows x 1 columns]
Причина, по которой это не разрешено, заключается в том, что без указаний (например, в numpy) вы можете сделать что-то вроде этого:
In [51]: df = DataFrame({ 'A' : [1,2,3] })
In [52]: df.loc[df['A'] == 2] = [ 5 ]
In [53]: df
Out[53]:
A
0 1
1 5
2 3
[3 rows x 1 columns]
Вы можете сделать присваивание, в котором длина значений True в маске равна длине списка / кортежа / ndarray в правой части (например, значение, которое вы устанавливаете). Панды допускают это, а также длину, которая точно равна lhs, и скаляр. Что-либо еще явно запрещено, потому что это неоднозначно (например, вы хотите выровнять это или нет?)
Например, представьте:
In [54]: df = DataFrame({ 'A' : [1,2,3] })
In [55]: df.loc[df['A']<3] = [5]
ValueError: cannot set using a list-like indexer with a different length than the value
Список 0-длины /tuple/ndarray считается ошибкой не потому, что это невозможно сделать, а, как правило, из-за ошибки пользователя, из-за которой неясно, что делать.
В итоге, не используйте списки внутри объекта панд. Это не эффективно, а просто делает интерпретацию трудной / невозможной.
Изменить: сохранил мой оригинальный ответ ниже, но я поднял его без тестирования, и это на самом деле не работает для меня.
import pandas as pd
import numpy as np
ser1 = pd.Series(['hi',None,np.nan])
ser2 = pd.Series([5,7,9])
df = pd.DataFrame([ser1,ser2]).T
Это джанки, я знаю. Кроме того, по-видимому, конструктор DataFrame (но не конструктор Series) приводит None к np.nan. Понятия не имею почему.
df.loc[1,0] = None
Итак, теперь у нас есть
0 1
0 'hi' 5
1 None 7
2 NaN 9
df.columns = ['col1','col2']
mask = np.equal(df['col1'], None)
df.loc[mask, 'col1'] = []
Но это ничего не назначает. Фрейм данных выглядит так же, как и раньше. Я следую рекомендованному использованию из документации и назначаю базовые типы (строки и числа). Поэтому для меня проблема заключается в назначении объектов для записей в данных. Понятия не имею, что случилось.
(Оригинальный ответ)
Две вещи:
- Я не знаком с
np.equal
ноpandas.isnull()
также должен работать, если вы хотите захватить все нулевые значения. - Вы делаете то, что называется "цепным назначением". Я не до конца понимаю проблему, но знаю, что она не работает. В документах.
Попробуй это:
mask = pandas.isnull(df[col])
df.loc[mask, col] = list()
Или, если вы хотите только поймать None
и не np.nan
:
mask = np.equal(df[col],None)
df.loc[mask, col] = list()