簡體   English   中英

pandas:pivot 在兩列上

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM