簡體   English   中英

如何在 pandas 中用空列表 [] 填充 dataframe Nan 值?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM