[英]pandas: pivot on two columns
我有以下数据:
import pandas as pd, numpy as np
dates = pd.date_range('01/01/2022', '01/11/2022', freq = 'D')
values = [0,0,1,1,0,0,1,1,1,0,1]
df = pd.DataFrame({'date': dates, 'value': values})
df
date value
0 2022-01-01 0
1 2022-01-02 0
2 2022-01-03 1
3 2022-01-04 1
4 2022-01-05 0
5 2022-01-06 0
6 2022-01-07 1
7 2022-01-08 1
8 2022-01-09 1
9 2022-01-10 0
10 2022-01-11 1
我想对此进行转换,以便我最终得到一个“开始”和“结束”列,这样开始是 1 的第一次出现,结束是 1 的最后一次连续出现。基本上我应该这样结束:
start end
2022-01-03 2022-01-04
2022-01-07 2022-01-09
2022-01-11
所以我到目前为止所做的是:
conditions = [
(df.value == 1) & (df.value.shift(1) == 0),
(df.value == 1) & (df.value.shift(-1) == 0)]
choices = ['start', 'end']
df['value'] = np.select(conditions, choices, default=pd.NA)
df = df.dropna()
df.pivot(columns='value')
date
value end start
2 NaT 2022-01-03
3 2022-01-04 NaT
6 NaT 2022-01-07
8 2022-01-09 NaT
10 NaT 2022-01-11
如您所见,它几乎就在那里……我现在可以做一些额外的摆弄以获得我想要的东西——但我觉得我可能以错误的方式接近它。
有没有更好、更有效的方法来解决这个问题?
将数据框split
成块,然后从 1 块中提取第一个/最后一个日期:
splits = np.split(df, np.flatnonzero(df['value'].diff() != 0))
pd.DataFrame([
(split['date'].iat[0], split['date'].iat[-1])
for split in splits
if len(split) > 0 and split['value'].iat[0] == 1
], columns=['start', 'end'])
# start end
#0 2022-01-03 2022-01-04
#1 2022-01-07 2022-01-09
#2 2022-01-11 2022-01-11
我会在这里使用groupby.agg
:
# which rows have value 1?
m = df['value'].eq(1)
(df[m] # keep only value==1
.groupby(m.ne(m.shift()).cumsum()) # group by consecutive values
['date'].agg(['first', 'last']) # get first and last date
.reset_index(drop=True)
)
output:
first last
0 2022-01-03 2022-01-04
1 2022-01-07 2022-01-09
2 2022-01-11 2022-01-11
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.