首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将日期向量转换为范围的Pythonic方法?

将日期向量转换为范围的Pythonic方法?
EN

Stack Overflow用户
提问于 2018-11-14 08:03:10
回答 2查看 49关注 0票数 2

我有一只熊猫DataFrame,每天一排,还有一些布尔列。我想把它们转换成一个DataFrame,它保存这些列是True的范围。

启动DF的示例:

代码语言:javascript
复制
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 (日期对象而不是字符串也可以,甚至首选):

代码语言:javascript
复制
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

作为扩展,在后续步骤中,我希望它可以用于多个列,例如:

代码语言:javascript
复制
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

有没有一种节奏曲,优雅的方式来做这件事--甚至是熊猫的功能?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-11-14 08:10:47

首先使用melt进行整形,然后通过cumsum为唯一组创建助手列,通过boolean indexing只过滤True,并通过函数firstlast聚合agg

代码语言:javascript
复制
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
票数 1
EN

Stack Overflow用户

发布于 2018-11-14 08:55:46

你可以试试pd.DataFrame.shift

首先,制作两个上下移动的新列。

代码语言:javascript
复制
df['down_shift'] = df['indic'].shift()
df['up_shift'] = df['indic'].shift(-1)

df会像

代码语言:javascript
复制
            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

这里的想法是

  • 案例1:(indic,down_shift) =(真,假)-开始
  • 案例2:(indic,up_shift) = (True,False) - end
  • 案例3:案例1和案例2同时发生-开始和结束

所以我们用这个伎俩

  • 真假=1
  • 假-真= -1
  • 真-真=0
  • 假-假=0

代码:

代码语言:javascript
复制
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

代码语言:javascript
复制
DatetimeIndex(['2018-01-03', '2018-01-09', '2018-01-12'], dtype='datetime64[ns]', freq=None)

然后我们检查end_date_list

代码语言:javascript
复制
DatetimeIndex(['2018-01-05', '2018-01-09'], dtype='datetime64[ns]', freq='4D')

最后一个日期不会从True更改为False,所以我们需要手动添加它。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53295483

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档