我有一个pandas df,如下:
MATERIAL DATE HIGH LOW
AAA 2022-01-01 10 0
AAA 2022-01-02 0 0
AAA 2022-01-03 5 2
BBB 2022-01-01 0 0
BBB 2022-01-02 10 5
BBB 2022-01-03 8 4
我想要
groupby
MATERIAL
和 sort_values
DATE
并选择组中除最后一行之外的所有行。
结果应该是:
MATERIAL DATE HIGH LOW
AAA 2022-01-01 10 0
AAA 2022-01-02 0 0
BBB 2022-01-01 0 0
BBB 2022-01-02 10 5
我已经尝试过
df.sort_values('DATE').groupby('MATERIAL').head(-1)
,但这会导致 df 为空。
DATE
是一个 pd.datetime
对象。
谢谢!
Series.duplicated
与 keep='last'
用于所有没有最后一个值:
df = df.sort_values(['MATERIAL','DATE'])
df = df[df['MATERIAL'].duplicated(keep='last')]
print (df)
MATERIAL DATE HIGH LOW
0 AAA 2022-01-01 10 0
1 AAA 2022-01-02 0 0
3 BBB 2022-01-01 0 0
4 BBB 2022-01-02 10 5
GroupBy.cumcount
降序计数并过滤没有 0
的所有行:
df = df.sort_values(['MATERIAL','DATE'])
df = df[df.groupby('MATERIAL').cumcount(ascending=False).ne(0)]
print (df)
MATERIAL DATE HIGH LOW
0 AAA 2022-01-01 10 0
1 AAA 2022-01-02 0 0
3 BBB 2022-01-01 0 0
4 BBB 2022-01-02 10 5
另一种方法是首先按日期排序,然后使用索引对除最后一行之外的每一行进行分组和获取:
>>> df.sort_values("DATE").groupby("MATERIAL").apply(lambda group_df: group_df.iloc[:-1])
MATERIAL DATE HIGH LOW
MATERIAL
AAA 0 AAA 2022-01-01 10 0
1 AAA 2022-01-02 0 0
BBB 3 BBB 2022-01-01 0 0
4 BBB 2022-01-02 10 5
您可以使用:
(df.groupby('MATERIAL', as_index=False, group_keys=False)
.apply(lambda d: d.iloc[:len(d)-1])
)
输出:
MATERIAL DATE HIGH LOW
0 AAA 2022-01-01 10 0
1 AAA 2022-01-02 0 0
3 BBB 2022-01-01 0 0
4 BBB 2022-01-02 10 5
另一种方法是使用
groupby+transform
并将 nth
设为 -1,并将其与 DATE 列进行比较,并仅选择与此不匹配的行:
df = df.sort_values(['MATERIAL','DATE'])
c = df['DATE'].ne(df.groupby("MATERIAL")['DATE'].transform('nth',-1))
out = df[c].copy()
print(out)
MATERIAL DATE HIGH LOW
0 AAA 2022-01-01 10 0
1 AAA 2022-01-02 0 0
3 BBB 2022-01-01 0 0
4 BBB 2022-01-02 10 5
旁注:由于您有一个日期列,您还可以使用
max
或 last
进行转换,但这只会限制您到最后一行,而不是例如您可能需要 nth
的倒数第二行
如上图:
c = df['DATE'].ne(df.groupby("MATERIAL")['DATE'].transform('max'))
鸭数据库:
(
df1.sql.select("*,row_number() over(partition by MATERIAL order by date desc) rn")
.filter("rn!=1")
)
MATERIAL DATE HIGH LOW
0 AAA 2022-01-01 10 0
1 AAA 2022-01-02 0 0
3 BBB 2022-01-01 0 0
4 BBB 2022-01-02 10 5