如何解决处理熊猫中的空值–在一列中使用过滤后的值在其他两列中填充nan 问:包含一些缺失值的单独列 A:使用fillna和str.contains
这是我发布的a recent question/answer的澄清/重述。我想知道我的解决方案是最简单还是最有效的选择。
问:包含一些缺失值的单独列
我有一个包含三列的数据框:df.location
,其字符串格式为逗号分隔的经度-纬度坐标,df.target
,目标变量,其整数在1到5之间,当前格式为浮点数,以及df.null
,该列主要是nan,但也混合了纬度-经度坐标,并且在1到5之间浮动。
这是一个df示例:
df = pd.DataFrame(
{'target': {0: nan,1: nan,2: nan,3: nan,4: nan,5: 4.0,6: 5.0,7: 4.0,8: 4.0,9: 4.0},'location': {0: nan,5: '41.69230795,-72.26691314',6: '41.70631764,-70.2868794',7: '41.70687995,-70.28684036',8: '41.70598417,-70.28671793',9: '41.69220757,-70.26687248'},'null': {0: '41.70477575,-70.28844073',1: '2',2: '41.70637091,-70.28704334',3: '4',4: '3',5: nan,6: nan,7: nan,8: nan,9: nan}
}
)
对于df.null
中存在不丢失值的每一行,df.target
和df.location
中的值均丢失。 (我不知道这是怎么发生的,但我检查了读取到Pandas Dataframe中的原始JSON,并确定当缺少位置和目标时,此null键会经常弹出。)这是Jupyter提供的Seaborn热图的屏幕截图笔记本来说明:
可以安全地假设df.location
和df.target
中的某些或所有缺失值都在df.null
中吗?如果是这样,如何根据这些值是纬度字符串还是目标浮点数将这些值移到适当的列中?
A:使用fillna()和str.contains()
处理到目前为止,这是我最好的答案-让我知道您的想法。基本上,我只是使用fillna(value=df.null)
来填充df.location
和df.target
中的所有缺失值:
df.target.fillna(
value=df.null,inplace=True
)
df.location.fillna(
value=df.null,inplace=True
)
然后,我使用正则表达式通过df.target
和df.location
布尔过滤器,并将所有不适当的值设置为np.nan
:
# Converting columns to type str so string methods work
df = df.astype(str)
# Using regex to change values that don't belong in column to NaN
regex = '[,]'
df.loc[df.target.str.contains(regex),'target'] = np.nan
regex = '^\d\.?0?$'
df.loc[df.location.str.contains(regex),'location'] = np.nan
# Returning `df.level` to float datatype (str is the correct
# datatype for `df.location`
df.target.astype(float)
有更好的方法吗?
编辑:更改fillna()单元代码,使其起作用。
解决方法
可以安全地假设df.location和df.target中的某些或所有缺失值都在df.null中吗?
这取决于初始数据。如果您有太多需要手动检查的内容,您将不知道。您可以在转换后检查数据框,但不确定。
我有了fillna(value=)
的新用法(感谢,我不太了解),我发现了一种更快的编写方法:
df = pd.DataFrame(
{'target': {0: nan,1: nan,2: nan,3: nan,4: nan,5: 4.0,6: 5.0,7: 4.0,8: 4.0,9: 4.0},'location': {0: nan,5: '41.69230795,-72.26691314',6: '41.70631764,-70.2868794',7: '41.70687995,-70.28684036',8: '41.70598417,-70.28671793',9: '41.69220757,-70.26687248'},'null': {0: '41.70477575,-70.28844073',1: '2',2: '41.70637091,-70.28704334',3: '4',4: '3',5: nan,6: nan,7: nan,8: nan,9: nan}
}
).assign(
target=lambda x: x.target.fillna(value=pd.to_numeric(x.null,errors='coerce')),location=lambda x: x.location.fillna(
value=x.loc[pd.to_numeric(x.null,errors='coerce').isnull(),'null']
)
).drop('null',axis='columns')
前面的代码给出了以下数据框:
location target
0 41.70477575,-70.28844073 NaN
1 NaN 2.0
2 41.70637091,-70.28704334 NaN
3 NaN 4.0
4 NaN 3.0
5 41.69230795,-72.26691314 4.0
6 41.70631764,-70.2868794 5.0
7 41.70687995,-70.28684036 4.0
8 41.70598417,-70.28671793 4.0
9 41.69220757,-70.26687248 4.0
您可以通过检查以下内容来检查null和target中是否没有值:
- 大于5的值(如果存在1,则您的假设为假,如果不是,则仍不确定:-))
- 位置栏中的昏迷数。
我留下的旧版本给出相同的结果。
以前的版本
此处进行的转换中不含正则表达式:
import pandas as pd
from numpy import nan
df = pd.DataFrame(
{'target': {0: nan,9: nan}
}
).assign(
# use the conversion to numeric of the null column in order to find values
# going to target and to location
new_target=lambda x: pd.to_numeric(x['null'],errors='coerce'),new_location=lambda x: x.loc[pd.to_numeric(x['null'],'null'],).assign(
target_without_nan=lambda x: x.new_target.fillna(0.0),new_location=lambda x: x.new_location.fillna(''),target=lambda x: (x.target_without_nan + x.target.fillna(0.0)).loc[~(x.target.isnull() & x.new_target.isnull())],location=lambda x: x.location.fillna('').str.cat(x.new_location.astype(str)).replace('',nan)
).loc[:,['location','target']]
我使用this answer中的技巧进行求和和连接,以替换初始列的nan
值。我还保留了nan
的值,这些值在上一次分配目标时无法用.loc
替换。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。