如何从数据框中删除空白/NA并将值上移

2025-03-12 08:55:00
admin
原创
55
摘要:问题描述:我有一个巨大的数据框,里面有值和空白/NA。我想从数据框中删除空白,并将下一个值在列中向上移动。考虑下面的示例数据框。import pandas as pd import numpy as np df = pd.DataFrame(np.random.randn(5,4)) df.iloc[1,2]...

问题描述:

我有一个巨大的数据框,里面有值和空白/NA。我想从数据框中删除空白,并将下一个值在列中向上移动。考虑下面的示例数据框。

import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.randn(5,4))
df.iloc[1,2] = np.NaN
df.iloc[0,1] = np.NaN
df.iloc[2,1] = np.NaN
df.iloc[2,0] = np.NaN
df

       0           1           2         3
0   1.857476      NaN      -0.462941   -0.600606
1   0.000267   -0.540645    NaN        0.492480
2   NaN           NaN      -0.803889   0.527973
3   0.566922    0.036393   -1.584926   2.278294
4   -0.243182   -0.221294   1.403478   1.574097

我希望我的输出如下所示

       0             1             2           3
0   1.857476    -0.540645     -0.462941   -0.600606
1   0.000267     0.036393     -0.803889    0.492480
2   0.566922    -0.221294     -1.584926    0.527973
3   -0.243182                  1.403478    2.278294
4                                          1.574097

我希望删除 NaN 并将下一个值上移。df.shift没有帮助。我尝试了多个循环和 if 语句并获得了所需的结果,但有没有更好的方法来完成它。


解决方案 1:

您可以apply使用dropna

np.random.seed(100)
df = pd.DataFrame(np.random.randn(5,4))
df.iloc[1,2] = np.NaN
df.iloc[0,1] = np.NaN
df.iloc[2,1] = np.NaN
df.iloc[2,0] = np.NaN
print (df)
          0         1         2         3
0 -1.749765       NaN  1.153036 -0.252436
1  0.981321  0.514219       NaN -1.070043
2       NaN       NaN -0.458027  0.435163
3 -0.583595  0.816847  0.672721 -0.104411
4 -0.531280  1.029733 -0.438136 -1.118318

df1 = df.apply(lambda x: pd.Series(x.dropna().values))
print (df1)
          0         1         2         3
0 -1.749765  0.514219  1.153036 -0.252436
1  0.981321  0.816847 -0.458027 -1.070043
2 -0.583595  1.029733  0.672721  0.435163
3 -0.531280       NaN -0.438136 -0.104411
4       NaN       NaN       NaN -1.118318

然后如果需要替换为空白处,会创建混合值(带有数字的字符串),某些功能可能会被破坏:

df1 = df.apply(lambda x: pd.Series(x.dropna().values)).fillna('')
print (df1)
          0         1         2         3
0  -1.74977  0.514219   1.15304 -0.252436
1  0.981321  0.816847 -0.458027 -1.070043
2 -0.583595   1.02973  0.672721  0.435163
3  -0.53128           -0.438136 -0.104411
4                               -1.118318

解决方案 2:

方法
这个想法是按 来对列进行排序,numpy以便将s 放在最后。我使用来保留非 内的顺序。最后,我对数组进行切片并重新分配。我接着使用
np.isnan`np.nankind='mergesort'np.nan`fillna

v = df.values
i = np.arange(v.shape[1])
a = np.isnan(v).argsort(0, kind='mergesort')
v[:] = v[a, i]
print(df.fillna(''))

          0         1         2         3
0   1.85748 -0.540645 -0.462941 -0.600606
1  0.000267  0.036393 -0.803889  0.492480
2  0.566922 -0.221294  -1.58493  0.527973
3 -0.243182             1.40348  2.278294
4                                1.574097

如果你不想改变数据框

v = df.values
i = np.arange(v.shape[1])
a = np.isnan(v).argsort(0, kind='mergesort')
pd.DataFrame(v[a, i], df.index, df.columns).fillna('')

这样做的目的是利用numpy速度

简单时间测试

在此处输入图片描述

解决方案 3:

通过 piRSquared 添加到解决方案中:这会将所有值向左移动,不是向上移动。

如果不是所有值都是数字,请使用pd.isnull

v = df.values
a = [[n]*v.shape[1] for n in range(v.shape[0])]
b = pd.isnull(v).argsort(axis=1, kind = 'mergesort')
# a is a matrix used to reference the row index, 
# b is a matrix used to reference the column index
# taking an entry from a and the respective entry from b (Same index), 
# we have a position that references an entry in v
v[a, b]

一点解释:

a是一个长度为 的列表v.shape[0],它看起来像这样:

[[0, 0, 0, 0],
 [1, 1, 1, 1],
 [2, 2, 2, 2],
 [3, 3, 3, 3],
 [4, 4, 4, 4],
 ...

这里发生的事情是,vmx n,我已经使ab mx都成立n,所以我们要做的是,将i,j和中的每个条目配对a,以获得行b中的元素与元素的值以及列中的元素的值。因此,如果我们有和两者都像上面的矩阵,则返回一个矩阵,其中第一行包含的副本,第二行包含的副本,依此类推。i,j`ai,jbabv[a,b]nv[0][0]n`v[1][1]

在解决方案 piRSquared 中,这i是一个列表而不是矩阵。因此,列表用于v.shape[0]次数,即每行一次。类似地,我们可以这样做:

a = [[n] for n in range(v.shape[0])]
# which looks like 
# [[0],[1],[2],[3]...]
# since we are trying to indicate the row indices of the matrix v as opposed to 
# [0, 1, 2, 3, ...] which refers to column indices  

如果有任何不清楚的地方请告诉我,谢谢:)

解决方案 4:

作为一个熊猫初学者,我无法立即理解@jezrael 背后的原因

df.apply(lambda x: pd.Series(x.dropna().values))

但我发现它通过重置列的索引来工作。df.apply(默认情况下)逐列工作,将每列视为一个系列。使用 df.dropna() 会删除 NaN,但不会更改剩余数字的索引,因此当将此列添加回数据框时,数字会返回到其原始位置,因为它们的索引仍然相同,空白处用 NaN 填充,重新创建原始数据框并且不会实现任何效果。

通过重置列的索引,在本例中,通过将系列更改为数组(使用 .values)并重新更改为系列(使用 pd.Series),只有所有数字后面的空白处(即列底部)才会用 NaN 填充。同样可以通过以下方式实现

df.apply(lambda x: x.dropna().reset_index(drop = True))

reset_index 的 (drop = True) 可防止旧索引成为新列。

我本来想将此作为对@jezrael 的回答的评论发布,但我的声誉不够高!

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2500  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1541  
  PLM(产品生命周期管理)项目对于企业优化产品研发流程、提升产品质量以及增强市场竞争力具有至关重要的意义。然而,在项目推进过程中,范围蔓延是一个常见且棘手的问题,它可能导致项目进度延迟、成本超支以及质量下降等一系列不良后果。因此,有效避免PLM项目范围蔓延成为项目成功的关键因素之一。以下将详细阐述三大管控策略,助力企业...
plm系统   16  
  PLM(产品生命周期管理)项目管理在企业产品研发与管理过程中扮演着至关重要的角色。随着市场竞争的加剧和产品复杂度的提升,PLM项目面临着诸多风险。准确量化风险优先级并采取有效措施应对,是确保项目成功的关键。五维评估矩阵作为一种有效的风险评估工具,能帮助项目管理者全面、系统地评估风险,为决策提供有力支持。五维评估矩阵概述...
免费plm软件   23  
  引言PLM(产品生命周期管理)开发流程对于企业产品的全生命周期管控至关重要。它涵盖了从产品概念设计到退役的各个阶段,直接影响着产品质量、开发周期以及企业的市场竞争力。在当今快速发展的科技环境下,客户对产品质量的要求日益提高,市场竞争也愈发激烈,这就使得优化PLM开发流程成为企业的必然选择。缺陷管理工具和六西格玛方法作为...
plm产品全生命周期管理   26  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用