pandas 如何删除具有连续值的特定行

3gtaxfhh  于 2023-03-06  发布在  其他
关注(0)|答案(2)|浏览(191)

我有一个Pandas Dataframe * df_next *,它是特定辖区的犯罪类型事件的每月汇总。例如,类似于:
| 识别号|年月日|共计|
| - ------|- ------|- ------|
| AL0010000|一九九一至零一年|小行星2024|
| AL0010000|一九九一至零二年|小行星3017|
| ...|...|...|
| 第0550300号|2018年11月|小行星30147|
| 第0550300号|2018年12月|小行星32148|
我想通过删除"总计"列中连续4个月的0值的行来减小 Dataframe 的大小。换句话说,如果一个ID连续4个月报告的犯罪总数为0,我想删除这4个月的数据块。我想对所有ID执行此操作。
我试过了

# Define a window size of 4
window_size = 4

# Apply a rolling window to the Total column for each ID
df_next['Total_rolling'] = df_next.groupby('ID')['Total'].rolling(window=window_size).reset_index(0, drop=True)

df_next['Remove'] = ((df_next['Total_rolling'].shift(window_size - 1) == 0) & (df_next['Total_rolling'] == 0))

# Filter out the rows where there are four consecutive 0's in the Total value for each ID
df_filtered = df_next[~df_next['Remove']]

但是,当我检查df_filtered时,我仍然有多个连续四个月犯罪总数为0的ID示例。

20jt8wwn

20jt8wwn1#

注解代码
# is total zero?
m = df['Total'] == 0

# create a counter to identify different 
# blocks of consecutive zero's
b = (~m).cumsum()

# Group the rows where total is zero by `ID` and above blocks
# and transform with size to calculate the number of consecutive zeros
s = df[m].groupby(['ID', b]).transform('size')

# Drop the rows from the original dataframe where
# there are 4 or more consecutive zeros
df = df.drop(s.index[s >= 4])
yqkkidmi

yqkkidmi2#

这将做我认为你的问题问:

d = df.sort_values(['ID','Year_Month']).pipe(
    lambda d:d.assign(isZero=d.Total.eq(0)))[['ID','isZero']]
d['cumZeros'] = d.groupby('ID').isZero.cumsum()
d['cumZerosAtLastBreak'] = ( d.groupby('ID').cumZeros
    .transform(lambda s: s[s.eq(s.shift(1))]) )
d['cumZerosAtLastBreak'] = ( d.groupby('ID').cumZerosAtLastBreak
    .transform(lambda s:s.ffill().fillna(0, downcast='infer')) )
res = df.loc[d.cumZeros - d.cumZerosAtLastBreak < 4,:]

说明:

  • ID, Year_Month对原始 Dataframe 进行排序,添加isZero列,其中布尔值指示Total是否为0,并删除除ID, isZero以外的所有列
  • 对于每个ID组,将cumZeros列与isZerocumsum相加
  • 对于每个ID组,添加cumZerosAtLastBreak列,该列从cumZeros复制具有cumZeros == cumZeros.shift(1)的行的值,否则为NaN(这为我们提供了零的累计数量,但仅适用于标记零条纹中断的行)
  • 对每个ID组使用ffillfillna(0)更新cumZerosAtLastBreak列(并向下转换为int,只是为了保持逻辑一致性
  • 过滤原始 Dataframe ,仅保留cumZeros - cumZerosAtLastBreak < 4的行(即零条纹长度小于4的行)。

样品输入:

ID Year_Month  Total
0   AL0010000    2020-01      0
1   AL0010000    2020-02      0
2   AL0010000    2020-03      0
3   AL0010000    2020-04      0
4   AL0010000    2020-05    123
5   AL0010000    2020-06      0
6   AL0010000    2020-07      0
7   AL0010000    2020-08      0
8   AL0010000    2020-09      0
9   AL0010000    2020-10      0
10  AL0010000    2020-11      0
11  AL0010000    2020-12    456
12  WV0550300    2021-01      0
13  WV0550300    2021-02      0
14  WV0550300    2021-03      0
15  WV0550300    2021-04      0
16  WV0550300    2021-05    123
17  WV0550300    2021-06      0
18  WV0550300    2021-07      0
19  WV0550300    2021-08      0
20  WV0550300    2021-09      0
21  WV0550300    2021-10      0
22  WV0550300    2021-11      0
23  WV0550300    2021-12    456

输出:

ID Year_Month  Total
0   AL0010000    2020-01      0
1   AL0010000    2020-02      0
2   AL0010000    2020-03      0
4   AL0010000    2020-05    123
5   AL0010000    2020-06      0
6   AL0010000    2020-07      0
7   AL0010000    2020-08      0
11  AL0010000    2020-12    456
12  WV0550300    2021-01      0
13  WV0550300    2021-02      0
14  WV0550300    2021-03      0
16  WV0550300    2021-05    123
17  WV0550300    2021-06      0
18  WV0550300    2021-07      0
19  WV0550300    2021-08      0
23  WV0550300    2021-12    456

相关问题