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 或其他任何东西,但我无法弄清楚如何将每一行强行向左移动。
答案 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_axis
对 s
中的值进行排序,并在给定的数据帧 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