我有一个大型数据框(400,000多行),如下所示:
data = np.array([
[1949, '01/01/2018', np.nan, 17, '30/11/2017'],
[1949, '01/01/2018', np.nan, 19, np.nan],
[1811, '01/01/2018', 16, np.nan, '31/11/2017'],
[1949, '01/01/2018', 15, 21, '01/12/2017'],
[1949, '01/01/2018', np.nan, 20, np.nan],
[3212, '01/01/2018', 21, 17, '31/11/2017']
])
columns = ['id', 'ReceivedDate', 'PropertyType', 'MeterType', 'VisitDate']
pd.DataFrame(data, columns=columns)
结果df:
id ReceivedDate PropertyType MeterType VisitDate
0 1949 01/01/2018 NaN 17 30/11/2017
1 1949 01/01/2018 NaN 19 NaN
2 1811 01/01/2018 16 NaN 31/11/2017
3 1949 01/01/2018 15 21 01/12/2017
4 1949 01/01/2018 NaN 20 NaN
5 3212 01/01/2018 21 17 31/11/2017
我想基于groupby(id&收到日期)转发填充 - 只要它们按顺序在索引中排序(即只有前向填充索引位置1和4)。
我正在考虑有一个专栏,说明是否应该根据标准填写,但我如何查看上面的行?
(我计划使用这个答案的解决方案:pandas fill forward performance issue
df.isnull().astype(int)).groupby(level=0).cumsum().applymap(lambda x: None if x == 0 else 1)
因为x = df.groupby(['id','ReceivedDate']).ffill()
非常慢。)
所需的df:
id ReceivedDate PropertyType MeterType VisitDate
0 1949 01/01/2018 NaN 17 30/11/2017
1 1949 01/01/2018 NaN 19 30/11/2017
2 1811 01/01/2018 16 NaN 31/11/2017
3 1949 01/01/2018 15 21 01/12/2017
4 1949 01/01/2018 15 20 01/12/2017
5 3212 01/01/2018 21 17 31/11/2017
答案 0 :(得分:1)
选项1
groupby
+ ffill
与limit=1
-
df.groupby(['id', 'ReceivedDate']).ffill(limit=1)
id ReceivedDate PropertyType MeterType VisitDate
0 1949 01/01/2018 NaN 17 30/11/2017
1 1949 01/01/2018 NaN 19 30/11/2017
2 1811 01/01/2018 16 18 31/11/2017
3 1949 01/01/2018 15 21 01/12/2017
4 1949 01/01/2018 15 20 01/12/2017
5 3212 01/01/2018 21 17 31/11/2017
选项2
代替groupby
+ ffill
,尝试使用groupby
,mask
和shift
填充NaN -
i = df[['id', 'ReceivedDate']]
j = i.ne(i.shift().values).any(1).cumsum()
df.mask(df.isnull().astype(int).groupby(j).cumsum().eq(1), df.groupby(j).shift())
或者,
df.where(df.isnull().astype(int).groupby(j).cumsum().ne(1), df.groupby(j).shift())
id ReceivedDate PropertyType MeterType VisitDate
0 1949 01/01/2018 NaN 17 30/11/2017
1 1949 01/01/2018 NaN 19 30/11/2017
2 1811 01/01/2018 16 18 31/11/2017
3 1949 01/01/2018 15 21 01/12/2017
4 1949 01/01/2018 15 20 01/12/2017
5 3212 01/01/2018 21 17 31/11/2017
答案 1 :(得分:1)
cols_to_ffill = ['PropertyType', 'VisitDate']
i = df.copy()
newdata = pd.DataFrame(['placeholder'] )
while not newdata.index.empty:
RowAboveid = i.id.shift()
RowAboveRD = i.ReceivedDate.shift()
rows_with_cols_to_ffill_all_empty = i.loc[:, cols_to_ffill].isnull().all(axis=1)
rows_to_ffill = (i.ReceivedDate == RowAboveRD) & (i.id == RowAboveid) & (rows_with_cols_to_ffill_all_empty)
rows_used_to_fill = i[rows_to_ffill].index-1
newdata = i.loc[rows_used_to_fill, cols_to_ffill]
newdata.index +=1
i.loc[rows_to_ffill, cols_to_ffill] = newdata
保持循环直到不再匹配(即所有列都向前填充。)