有效地从 Pandas 数据框中删除所有零

时间:2021-03-21 13:46:57

标签: python pandas data-cleaning

train_subset.iloc[:10, :10]
1  0  7045    17    16.0    0.0    0.0   0.0   0.0  18.0
1  0  8907   137    48.0   42.0   53.0  32.0  35.0  30.0
1  0   917   167   193.0   88.0   48.0   0.0  24.0   0.0
1  0   203  5303  2073.0  153.0  108.0  97.0  73.0  89.0
1  0   198   817   198.0    0.0    0.0  88.0  93.0  70.0

我有一个名为 train 的数据集。我在这里打印了它的一小部分。

是否有一种有效的方法可以从数据集中删除所有零,通过向左移动来更新列?例如,我想要的输出是...

请注意,我希望这仅从第 4 列开始触发。第一、第二、第三列是元数据,不应更改。

train_subset.iloc[:10, :10]
1  0  7045    17    16.0   18.0
1  0  8907   137    48.0   42.0   53.0  32.0  35.0  30.0
1  0   917   167   193.0   88.0   48.0  24.0 
1  0   203  5303  2073.0  153.0  108.0  97.0  73.0  89.0
1  0   198   817   198.0   88.0   93.0  70.0

本质上,您可以将每一行视为一个时间序列,我想忽略任何零。所以我只在事件发生的时间点有读数,而且我已经删除了两者之间的所有零。

我可以弄清楚如何删除零并替换为 NA 或其他任何东西,但我无法弄清楚如何将每一行强行向左移动。

1 个答案:

答案 0 :(得分:6)

np.argsort + boolean masking

s = df.iloc[:, 3:]
i = np.argsort(s.eq(0), axis=1)
df.iloc[:, 3:] = np.take_along_axis(s[s.ne(0)].values, i.values, axis=1)

说明

fourth 列开始对给定数据帧的部分进行切片,然后将其与 0 进行比较以创建布尔掩码。创建布尔掩码背后的想法是,当我们在下一步对掩码进行排序时,False 值将首先出现,同时还保持相对顺序,这基本上提供了类似 shift 的行为。

>>> s.eq(0)

       3      4      5      6      7      8      9
0  False  False   True   True   True   True  False
1  False  False  False  False  False  False  False
2  False  False  False  False   True  False   True
3  False  False  False  False  False  False  False
4  False  False   True   True  False  False  False

现在在上面的掩码上使用 np.argsort 来获取将 sort 数据帧切片 s 中的值的索引。

>>> np.argsort(s.eq(0), axis=1)

   3  4  5  6  7  8  9
0  0  1  6  2  3  4  5
1  0  1  2  3  4  5  6
2  0  1  2  3  5  4  6
3  0  1  2  3  4  5  6
4  0  1  4  5  6  2  3

然后使用带有上述索引的 np.take_along_axiss 中的值进行排序,并在给定的数据帧 df 中分配这些排序后的值。

>>> np.take_along_axis(s[s.ne(0)].values, i.values, axis=1)

array([[  17.,   16.,   18.,   nan,   nan,   nan,   nan],
       [ 137.,   48.,   42.,   53.,   32.,   35.,   30.],
       [ 167.,  193.,   88.,   48.,   24.,   nan,   nan],
       [5303., 2073.,  153.,  108.,   97.,   73.,   89.],
       [ 817.,  198.,   88.,   93.,   70.,   nan,   nan]])

结果

>>> df

   0  1     2       3       4      5      6     7     8     9
0  1  0  7045    17.0    16.0   18.0    NaN   NaN   NaN   NaN
1  1  0  8907   137.0    48.0   42.0   53.0  32.0  35.0  30.0
2  1  0   917   167.0   193.0   88.0   48.0  24.0   NaN   NaN
3  1  0   203  5303.0  2073.0  153.0  108.0  97.0  73.0  89.0
4  1  0   198   817.0   198.0   88.0   93.0  70.0   NaN   NaN