Python pandas 使用 fillna() 来避免对 NaN 值进行错误拆分

Posted

技术标签:

【中文标题】Python pandas 使用 fillna() 来避免对 NaN 值进行错误拆分【英文标题】:Python pandas use fillna() to avoid error splitting on NaN value 【发布时间】:2022-01-23 22:26:34 【问题描述】:
my_df = pd.DataFrame(data =  'col0': ['1%2%', '3%4%'], 'col1': [np.nan, np.nan], 'col2': ['+1-2', '+2-4'], 'col3': [np.nan, '+2-4'], 'col4': [np.nan, np.nan] )

my_df[['col0a', 'col0b']] = my_df['col0'].fillna('%').str.split('%', expand = True).iloc[:, 0:2]
my_df[['col1a', 'col1b']] = my_df['col1'].fillna('%').str.split('%', expand = True).iloc[:, 0:2]
my_df[['col2a', 'col2b']] = my_df['col2'].str.split('(?<=[\d]|K)(?=[+-])', expand=True)
my_df[['col3a', 'col3b']] = my_df['col3'].str.split('(?<=[\d]|K)(?=[+-])', expand=True)
my_df[['col4a', 'col4b']] = my_df['col4'].str.split('(?<=[\d]|K)(?=[+-])', expand=True)

my_df

这会在my_df[['col4a', 'col4b']] 行引发错误,因为整列都是NaN 值。对于col1,没有抛出错误,因为我们用% 填充,然后拆分在% 上拆分,导致两列包含空字符串,这正是我们想要的。

我们可以在col4 中添加什么fillna() 使其不会引发错误? col4 的拆分比 col1 的拆分更复杂(寻找 +#-# 的模式)。我们已经尝试过fillna('+-'),但这不起作用。一般来说,我们正在寻找一种解决方案,当col4 的值为NaN 时,为col4acol4b 输出空字符串。

编辑: 措辞不同,我需要一个用于 fillna 的字符串,当传递给 .split('(?&lt;=[\d]|K)(?=[+-])', expand=True) 时,会产生 2 个空字符串,尽管也许我可以用 fillna(+9999-9999) 之类的东西替换,然后用空字符串替换 9999...

【问题讨论】:

问题不在于拆分返回NaN。问题是拆分没有发生,因为 NaN 存在,并且用空字符串替换 NaN 不起作用,因为拆分输出需要 2 列。 【参考方案1】:

一个(可能)更好的解决方案是使用.str.extract 而不是.str.split,这更适合您的目的:

my_df = pd.DataFrame(data =  'col0': ['1%2%', '3%4%'], 'col1': [np.nan, np.nan], 'col2': ['+1-2', '+2-4'], 'col3': [np.nan, '+2-4'], 'col4': [np.nan, np.nan] )
my_df = my_df.fillna('')

pat1 = r'(\d+%)(\d+%)'
pat2 = r'([+-](?:[\d]+|K))([+-](?:[\d]+|K))'

my_df[['col0a', 'col0b']] = my_df['col0'].str.extract(pat1)
my_df[['col1a', 'col1b']] = my_df['col1'].str.extract(pat1)
my_df[['col2a', 'col2b']] = my_df['col2'].str.extract(pat2)
my_df[['col3a', 'col3b']] = my_df['col3'].str.extract(pat2)
my_df[['col4a', 'col4b']] = my_df['col4'].str.extract(pat2)
my_df = my_df.fillna('')

输出:

>>> my_df
   col0 col1  col2  col3 col4 col0a col0b col1a col1b col2a col2b col3a col3b col4a col4b
0  1%2%       +1-2               1%    2%                +1    -2                        
1  3%4%       +2-4  +2-4         3%    4%                +2    -4    +2    -4

【讨论】:

这很棒。我想我会在最后 5 行的每一行末尾添加 fillna(''),因为我更喜欢空字符串而不是 NaN,但另一方面,这看起来真的很好 @Canovic 请立即查看答案。我已经按照你说的做了,只是更简洁一点;) 我猜这里有一个问题是col0acol0b 在输出中丢失了% 登录 容易补救。请立即检查答案@Canovic ;)【参考方案2】:

并不完美,但这个 2 行解决方案比我目前使用的使用 if: else: 块的 8 行解决方案要好。

my_df[['col4a', 'col4b']] = my_df['col4'].fillna('+999999-999999').str.split('(?<=[\d]|K)(?=[+-])', expand=True)
my_df[['col4a', 'col4b']] = my_df[['col4a', 'col4b']].replace('+999999', '').replace('-999999', '')

【讨论】:

以上是关于Python pandas 使用 fillna() 来避免对 NaN 值进行错误拆分的主要内容,如果未能解决你的问题,请参考以下文章

Python pandas 使用 fillna() 来避免对 NaN 值进行错误拆分

数据分析——python,pandas:DataFrame对象(merge函数,fillna函数的使用)排序

Python Pandas Fillna 中位数不起作用

Fillna 一次使用多种方法 - pandas

使用 fillna 在 Pandas 中使用列表填充空值

Pandas fillna('Missing')