Имам pandas DataFrame, където всяка клетка съдържа питън dict.
>>> data = {"Q":{"X":{2:2010}, "Y":{2:2011, 3:2009}},"R":{"X":{1:2013}}}
>>> frame = DataFrame(data)
>>> frame
Q R
X {2: 2010} {1: 2013}
Y {2: 2011, 3: 2009} NaN
Бих искал да замени NN с празен dict, за да получите този резултат:
Q R
X {2: 2010} {1: 2013}
Y {2: 2011, 3: 2009} {}
Въпреки това, защото fillna
функцията тълкува празния dict не като скаларна стойност, а като изобразяване на колоната -> стойност, НЕ НЕ, ако просто правя това (т.е. не работи):
>>> frame.fillna(inplace=True, value={})
Q R
X {2: 2010} {1: 2013}
Y {2: 2011, 3: 2009} NaN
Има ли начин да се използва fillna
да постигне това, което искам? Трябва ли да повторя през цялата DataFrame или да конструирам глупав dict с всичките ми колони, присвоени на празен dict?
Отговори:
5 за отговор № 1Успях да използвам DataFrame.applymap
по този начин:
>>> from pandas import isnull
>>> frame=frame.applymap(lambda x: {} if isnull(x) else x)
>>> frame
Q R
X {2: 2010} {1: 2013}
Y {2: 2011, 3: 2009} {}
Това решение избягва клопките и в двата случаяРешението на EdChum (където всички NaN клетки завършват, сочейки в същата подлежаща dict обект в паметта, предотвратявайки ги да бъдат осъвременявани независимо един от друг) и Shashank (където потенциално голяма структура на данните трябва да бъде изградена с вложени dits, за да зададете единична празна стойност на dict).
2 за отговор № 2
Проблемът е, че когато се предаде дикт fillna
, той се опитва да запълни стойностите въз основа на колоните в рамката. Така че първото решение, което се опитах, беше -
frame.fillna({column: {} for column in frame.columns})
Но ако речникът се предоставя на второ ниво по този начин, той се опитва да съвпадне с клавишите с индекса, така че решението, което работи, е -
frame.fillna({column: {ind: {} for ind in frame.index} for column in frame.columns})
Което дава -
Q R
X {2: 2010} {1: 2013}
Y {2: 2011, 3: 2009} {}
Отговорът на EdChum вероятно е по-добър за вашите нужди, но това може да се използва, когато не искате да правите промени на място.
EDIT: Решението по-горе работи добре за по-малки кадри, но може да бъде проблем за по-големи рамки. Използвайки replace
може да реши това.
frame.replace(np.nan, {column: {} for column in frame.columns})
1 за отговор № 3
Това работи loc
:
In [6]:
frame.loc[frame["R"].isnull(), "R"] = {}
frame
Out[6]:
Q R
X {2: 2010} {1: 2013}
Y {2: 2011, 3: 2009} {}
0 за отговор № 4
употреба .values
accessor за директно присвояване в чисто масив:
frame.R = frame.R.astype(object) # assertion
frame.R.values[frame.R.isnull()] = {}