我有一只熊猫DataFrame,每天一排,还有一些布尔列。我想把它们转换成一个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,然后是2018-01-09 (只有一天),然后再从2018-01-12到2018-01-15。
我在本例中要寻找的输出是这个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有没有一种节奏曲,优雅的方式来做这件事--甚至是熊猫的功能?
发布于 2018-11-14 08:10:47
首先使用melt进行整形,然后通过cumsum为唯一组创建助手列,通过boolean indexing只过滤True,并通过函数first和last聚合agg。
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发布于 2018-11-14 08:55:46
你可以试试pd.DataFrame.shift
首先,制作两个上下移动的新列。
df['down_shift'] = df['indic'].shift()
df['up_shift'] = df['indic'].shift(-1)df会像
indic down_shift up_shift
2018-01-01 False NaN False
2018-01-02 False False True
2018-01-03 True False True
2018-01-04 True True True
2018-01-05 True True False
2018-01-06 False True False
2018-01-07 False False False
2018-01-08 False False True
2018-01-09 True False False
2018-01-10 False True False
2018-01-11 False False True
2018-01-12 True False True
2018-01-13 True True True
2018-01-14 True True True
2018-01-15 True True NaN这里的想法是
所以我们用这个伎俩
代码:
case_start = df['indic'] - df['down_shift']
case_end = df['indic'] - df['up_shift']
start_date_list = df[case_start == 1].index
end_date_list = df[case_end == 1].index然后我们检查start_date_list
DatetimeIndex(['2018-01-03', '2018-01-09', '2018-01-12'], dtype='datetime64[ns]', freq=None)然后我们检查end_date_list
DatetimeIndex(['2018-01-05', '2018-01-09'], dtype='datetime64[ns]', freq='4D')最后一个日期不会从True更改为False,所以我们需要手动添加它。
https://stackoverflow.com/questions/53295483
复制相似问题