![](/img/trans.png)
[英]How to fill dataframe Nan values with empty list [] of 4 elements in pandas?
[英]How to fill dataframe Nan values with empty list [] in pandas?
這是我的 dataframe:
date ids
0 2011-04-23 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,...
1 2011-04-24 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,...
2 2011-04-25 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,...
3 2011-04-26 Nan
4 2011-04-27 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,...
5 2011-04-28 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,...
我想用 [] 替換Nan
。 怎么做? Fillna([]) 不起作用。 我什至嘗試了replace(np.nan, [])
但它給出了錯誤:
TypeError('Invalid "to_replace" type: \'float\'',)
我的方法與@hellpanderrr 的方法類似,但是測試列表而不是使用isnan
:
df['ids'] = df['ids'].apply(lambda d: d if isinstance(d, list) else [])
我最初嘗試使用pd.isnull
(或pd.notnull
)但是,當給定一個列表時,它返回每個元素的空值。
經過大量的頭疼后,我發現這種方法應該是最有效的(沒有循環,沒有應用),只需分配給一個切片:
isnull = df.ids.isnull()
df.loc[isnull, 'ids'] = [ [[]] * isnull.sum() ]
訣竅是構建正確大小的[]
列表( isnull.sum()
),然后將其包含在一個列表中:您分配的值是一個二維數組(1 列, isnull.sum()
行)包含空列表作為元素。
一個簡單的解決方案是:
df['ids'].fillna("").apply(list)
正如@timgeb 所指出的,這要求df['ids']
僅包含列表或 nan。
您可以首先使用loc
定位在ids
列中具有nan
的所有行,然后使用at
循環遍歷這些行以將它們的值設置為空列表:
for row in df.loc[df.ids.isnull(), 'ids'].index:
df.at[row, 'ids'] = []
>>> df
date ids
0 2011-04-23 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
1 2011-04-24 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
2 2011-04-25 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
3 2011-04-26 []
4 2011-04-27 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
5 2011-04-28 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
令人驚訝的是,將帶有空列表的字典作為值傳遞似乎適用於Series.fillna
,但不適用於DataFrame.fillna
- 所以如果你想處理單個列,你可以使用它:
>>> df
A B C
0 0.0 2.0 NaN
1 NaN NaN 5.0
2 NaN 7.0 NaN
>>> df['C'].fillna({i: [] for i in df.index})
0 []
1 5
2 []
Name: C, dtype: object
該解決方案可以通過將其應用於每一列來擴展到 DataFrames。
>>> df.apply(lambda s: s.fillna({i: [] for i in df.index}))
A B C
0 0 2 []
1 [] [] 5
2 [] 7 []
注意:對於缺失值很少的大型系列/數據幀,這可能會創建大量的一次性空列表。
使用pandas
1.0.5 測試。
使用 numpy 的另一種解決方案:
df.ids = np.where(df.ids.isnull(), pd.Series([[]]*len(df)), df.ids)
或使用 combine_first:
df.ids = df.ids.combine_first(pd.Series([[]]*len(df)))
也許不是最簡短/優化的解決方案,但我認為它非常易讀:
# Packages
import ast
# Masking-in nans
mask = df['ids'].isna()
# Filling nans with a list-like string and literally-evaluating such string
df.loc[mask, 'ids'] = df.loc[mask, 'ids'].fillna('[]').apply(ast.literal_eval)
缺點是需要加載ast
package。
編輯
我最近發現了eval()
內置的存在。 這樣可以避免導入任何額外的 package。
# Masking-in nans
mask = df['ids'].isna()
# Filling nans with a list-like string and literally-evaluating such string
df.loc[mask, 'ids'] = df.loc[mask, 'ids'].fillna('[]').apply(eval)
無作業:
1)假設我們的 dataframe 中只有浮點數和整數
import math
df.apply(lambda x:x.apply(lambda x:[] if math.isnan(x) else x))
2) 對於任何 dataframe
import math
def isnan(x):
if isinstance(x, (int, long, float, complex)) and math.isnan(x):
return True
df.apply(lambda x:x.apply(lambda x:[] if isnan(x) else x))
也許更密集:
df['ids'] = [[] if type(x) != list else x for x in df['ids']]
這可能更快,一個班輪解決方案:
df['ids'].fillna('DELETE').apply(lambda x : [] if x=='DELETE' else x)
另一個明確的解決方案:
# use apply to only replace the nulls with the list
df.loc[df.ids.isnull(), 'ids'] = df.loc[df.ids.isnull(), 'ids'].apply(lambda x: [])
創建一個 function 檢查您的條件,如果沒有,它返回一個空列表/空集等。
然后將 function 應用於變量,但如果您願意,也可以將新計算的變量分配給舊變量或新變量。
aa=pd.DataFrame({'d':[1,1,2,3,3,np.NaN],'r':[3,5,5,5,5,'e']})
def check_condition(x):
if x>0:
return x
else:
return list()
aa['d]=aa.d.apply(lambda x:check_condition(x))
你可以試試這個:
df.fillna(df.notna().applymap(lambda x: x or []))
list
中不支持fillna
方法,但你可以用dict
來代替。
df.fillna({})
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.