避免合并空值的最佳方法
Posted
技术标签:
【中文标题】避免合并空值的最佳方法【英文标题】:Best way to avoid merge nulls 【发布时间】:2018-02-11 17:19:15 【问题描述】:假设我有这 2 个 pandas 数据框。
In [3]: df1 = pd.DataFrame('id':[None,20,None,40,50],'value':[1,2,3,4,5])
In [4]: df2 = pd.DataFrame('index':[None,20,None], 'value':[1,2,3])
In [7]: df1
Out[7]: id value
0 NaN 1
1 20.0 2
2 NaN 3
3 40.0 4
4 50.0 5
In [8]: df2
Out[8]: index value
0 NaN 1
1 20.0 2
2 NaN 3
当我合并这些数据帧时(基于 id 和 index 列) - 结果包括 id 和 index 缺少值的行。
df3 = df1.merge(df2, left_on='id', right_on = 'index', how='inner')
In [9]: df3
Out[9]: id value_x index value_y
0 NaN 1 NaN 1
1 NaN 1 NaN 3
2 NaN 3 NaN 1
3 NaN 3 NaN 3
4 20.0 2 20.0 2
这是我尝试过的,但我想这不是最好的解决方案:
我用一个数据框列中的某个值替换了所有缺失值, 在第二个数据帧中也是如此,但具有另一个值 - 目的是条件将返回 False 并且行不会出现在结果中。
In [14]: df1_fill = df1.fillna('id':'NONE1')
In [13]: df2_fill = df2.fillna('index':'NONE2')
In [15]: df1_fill
Out[15]: id value
0 NONE1 1
1 20 2
2 NONE1 3
3 40 4
4 50 5
In [16]: df2_fill
Out[16]: index value
0 NONE2 1
1 20 2
2 NONE2 3
该问题的最佳解决方案是什么?
此外,在示例中 - 连接列的 daya 类型是数字,但它可以是其他类型,如文本或日期...
编辑:
因此,通过此处的解决方案,我可以使用 dropna 函数在连接之前删除具有缺失值的行 - 但对于我根本不想要这些行的内部连接来说,这很好。
左连接还是完全连接呢?
假设我有我以前使用过的那 2 个数据帧 - df1、df2。
所以对于内连接和左连接,我真的可以使用 dropna 函数:
In [61]: df_inner = df1.dropna(subset=['id']).merge(df2.dropna(subset=['index']), left_on='id', right_on = 'index', how='inner')
In [62]: df_inner
Out[62]: id value_x index value_y
0 20.0 2 20.0 6
In [63]: df_left = df1.merge(df2.dropna(subset=['index']), left_on='id', right_on = 'index', how='left')
In [64]: df_left
Out[64]: id value_x index value_y
0 NaN 1 NaN NaN
1 20.0 2 20.0 6.0
2 NaN 3 NaN NaN
3 40.0 4 NaN NaN
4 50.0 5 NaN NaN
In [65]: df_full = df1.merge(df2, left_on='id', right_on = 'index', how='outer')
In [66]: df_full
Out[66]: id value_x index value_y
0 NaN 1 NaN 5.0
1 NaN 1 NaN 7.0
2 NaN 3 NaN 5.0
3 NaN 3 NaN 7.0
4 20.0 2 20.0 6.0
5 40.0 4 NaN NaN
6 50.0 5 NaN NaN
在左侧,我从“右侧”数据框中删除了缺失值行,然后使用了合并。
没关系,因为在左连接中你知道如果条件返回 false,你在右源列中有 null - 所以行是否真的存在或者它们只是返回 false 并不重要。
但对于完全连接 - 我需要来自 2 个来源的所有行...
我不能使用 dropna,因为它会删除我需要的行,如果我不使用它 - 我会得到错误的结果。
谢谢。
【问题讨论】:
你希望输出是什么样的? 【参考方案1】:为什么不这样做:
pd.merge(df1.dropna(subset=['id']), df2.dropna(subset=['index']),
left_on='id',right_on='index', how='inner')
输出:
id value_x index value_y
0 20.0 2 20.0 2
【讨论】:
【参考方案2】:如果您不想要 nan 值,则可以删除 nan 值,即
df3 = df1.merge(df2, left_on='id', right_on = 'index', how='inner').dropna()
或
df3 = df1.dropna().merge(df2.dropna(), left_on='id', right_on = 'index', how='inner')
输出:
id value_x index value_y
0 20.0 2 20.0 2
对于合并后的外部合并删除即。
df_full = df1.merge(df2, left_on='id', right_on = 'index', how='outer').dropna(subset = ['id'])
输出:
id value_x index value_y
4 20.0 2 20.0 2.0
5 40.0 4 NaN NaN
6 50.0 5 NaN NaN
【讨论】:
好的,left\full join怎么样? 如果你添加了预期的输出。这将有助于提供更好的解决方案。 谢谢,但没有完全连接的预期结果:我预计 7 行(来自 df1 的 4 个“唯一”行,来自 df2 的 2 个“唯一”行,只有 1 个公共行 -条件返回真)【参考方案3】:由于您正在执行“内部”连接,因此您可以在合并之前删除 df1 中 id 列为 NaN 的行。
df1_nonan = df1.dropna(subset = ['id'])
df3 = df1_nonan.merge(df2, left_on='id', right_on = 'index', how='inner')
【讨论】:
以上是关于避免合并空值的最佳方法的主要内容,如果未能解决你的问题,请参考以下文章
有没有办法避免在 Apollo GraphQL 中返回具有空值的键?
SqlDataReader 检查空值的最佳方法 -sqlDataReader.IsDBNull vs DBNull.Value