我有一个 pandas DataFrame,每天一行,还有一些 bool 列。我想将它们转换为一个 DataFrame,其中包含这些列为 True 的范围。
启动 DF 的示例:
import pandas as pd
t = True
f = False
df = pd.DataFrame(
{'indic': [f, f, t, t, t, f, f, f, t, f, f, t, t, t, t]},
index=pd.date_range("2018-01-01", "2018-01-15")
)
print(df)
indic
2018-01-01 False
2018-01-02 False
2018-01-03 True
2018-01-04 True
2018-01-05 True
2018-01-06 False
2018-01-07 False
2018-01-08 False
2018-01-09 True
2018-01-10 False
2018-01-11 False
2018-01-12 True
2018-01-13 True
2018-01-14 True
2018-01-15 True
此 DataFrame 的列从 2018-01-03 到 2018-01-05 为 True,然后在 2018-01-09(仅一天),然后从 2018-01-12 到 2018-01-15 再次为 True。
我在这个例子中寻找的输出是这个 DF (日期对象而不是字符串也可以,甚至是首选):
desired_result = pd.DataFrame({
'from': ["2018-01-03", "2018-01-09", "2018-01-12"],
'to': ["2018-01-05", "2018-01-09", "2018-01-15"]
})
print(desired_result)
from to
0 2018-01-03 2018-01-05
1 2018-01-09 2018-01-09
2 2018-01-12 2018-01-15
作为扩展,在后续步骤中我希望它适用于多个列,例如:
df = pd.DataFrame(
{
'indic_A': [f, f, t, t, t, f, f, f, t, f, f, t, t, t, t],
'indic_B': [f, f, f, f, f, f, f, f, t, t, t, t, t, f, f]
},
index=pd.date_range("2018-01-01", "2018-01-15")
)
desired_result = pd.DataFrame({
'from': ["2018-01-03", "2018-01-09", "2018-01-12", "2018-01-09"],
'to': ["2018-01-05", "2018-01-09", "2018-01-15", "2018-01-13"],
'what': ["indic_A", "indic_A", "indic_A", "indic_B"]
})
print(desired_result)
from to what
0 2018-01-03 2018-01-05 indic_A
1 2018-01-09 2018-01-09 indic_A
2 2018-01-12 2018-01-15 indic_A
3 2018-01-09 2018-01-13 indic_B
有没有一种Python式的、优雅的方法来做到这一点——甚至可能是pandas函数?
最佳答案
使用melt
首先进行 reshape ,然后通过 cumsum
为唯一组创建辅助列,仅按boolean indexing
过滤True
和聚合agg
按功能 first
和 last
:
df = df.rename_axis('date').reset_index().melt('date', var_name='ind', value_name='boolean')
df['new'] = (~df['boolean']).cumsum()
df = (df[df['boolean']]
.groupby('new')
.agg({'date':['first','last'], 'ind':'first'})
.reset_index(drop=True))
df.columns = df.columns.map('_'.join)
print (df)
date_first date_last ind_first
0 2018-01-03 2018-01-05 indic_A
1 2018-01-09 2018-01-09 indic_A
2 2018-01-12 2018-01-15 indic_A
3 2018-01-09 2018-01-13 indic_B
关于将日期向量转换为范围的 Pythonic 方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53295483/