【发布时间】:2020-10-23 16:29:37
【问题描述】:
我有一个 Pandas 数据框,其中包含一个 id 列、一个日期列 dt 和一些可能包含 0 或 1(或根本没有值)的二进制列。
import pandas as pd
import datetime
# initialize list of lists
data = [
['A', None, None, 0, 0, datetime.date(2020,5,1)],
['A', 1, None, 0, 1, datetime.date(2020,5,2)],
['A', None, 1, 0, 0, datetime.date(2020,5,3)],
['B', 1, 1, 0, None, datetime.date(2020,5,3)]
]
# Create the pandas DataFrame
df = pd.DataFrame(data, columns = ['id', 'd1', 'd2', 'd3', 'd4', 'dt'])
# print dataframe.
df
id d1 d2 d3 d4 dt
0 A NaN NaN 0 0.0 2020-05-01
1 A 1.0 NaN 0 1.0 2020-05-02
2 A NaN 1.0 0 0.0 2020-05-03
3 B 1.0 1.0 0 NaN 2020-05-03
对于每个 ID,在任何给定日期,我都想跟踪二进制列从最早日期到最近日期的变化,保持最新值,但 忽略从数字到无的任何变化.
每个 ID 将有一行显示最新的已知值。
为了澄清,对于每个 ID,从最早日期到最近日期逐行:
- 如果列值从无变为数字,则使用数字作为最新的已知值
- 如果列值从 0 变为 1,则使用 1 作为最新的已知值
- 如果列值从 1 变为 0,则使用 0 作为最新的已知值
- 但是,如果列从数字更改为无,则将数字保留为最新的已知值
例如,在上面的数据框中,对于id ='A':
2020 年 5 月 2 日,该值将是 'A', 1, None, 0, 1(因为 d1 从 None 变为 1,d4 从 0 变为 1)
在 2020 年 5 月 3 日,该值将为 'A', 1, 1, 0, 0(因为 d2 从 None 变为 1 并且 d4 从 1 变为 0,但是 d1 从 1 变为 None 所以仍然保留 1 而不是无,因为这是最后一个已知值)
我对如何跟踪这样的更改有点迷茫。有什么方法可以在 lambda 中应用 shift 还是编写自定义函数来逐行比较?
df.groupby('id').apply(lambda x: x.sort_values(by='dt'). ???)
编辑添加:最后,我只想要一个数据框,每个 ID 有一行,所有二进制列的最新已知值。
id d1 d2 d3 d4
0 A 1 1 0 0
1 B 1 1 0 NaN
任何帮助将不胜感激!
【问题讨论】:
-
我不确定这个决定的标准是什么,所以我无法回应,但很容易让它成为一个垂直持有记录。我要对你说的就这些了吗?
-
@r-beginners 标准相当简单 - 对于每个组(按 ID),我必须将每一行与前一行进行比较......所以我从 5 月 1 日开始,初始化每个 @987654335 @;然后在 5 月 2 日,将这些列的值与上一行(即 5 月 1 日)进行比较,如果有任何更改为数字,我使用新值,否则保持不变;然后在 5 月 3 日做同样的事情,与已知值进行比较,依此类推。我只在列中的值更改为数字时更新(所以 null 到 0 或 1 是可以的。0 到 1 反之亦然反之亦然.. 但如果数字变为 null,则不更新)
-
为了响应cmet,我又写了代码,但是有一个地方有一个决策逻辑无法改进,原来是这样。如果你愿意,我仍然会发布。很抱歉我帮不了你。
-
没问题,@r-beginners - 感谢您对我的耐心和帮助 :) 我想出了一个解决方案并将其发布在答案下方。
标签: python pandas dataframe aggregate pandas-groupby