【问题标题】:Sort a dataframe by day, but excluding the year按天对数据框进行排序,但不包括年份
【发布时间】:2020-04-13 09:55:29
【问题描述】:

我正在处理一个包含多年数据的数据帧,每个值都有一个时间戳。我正在为夏季/非夏季月份的数据排序而苦苦挣扎。我不确定如何告诉 pandas 获取日期为 6 月 15 日至 9 月 15 日的数据,但会丢弃年份。

df['is_summer'] = df['Date'].dt.month.between(6,9) # This works for June 1 to September 30 for every year
# I want to do this, this is pseudo code
df['is_summer'] = df['Date'].dt.day.between(6-15,9-15) # From June 15 to September 15 for every year
# I also want to this 
df['is_late_night'] = df['Date'].dt.time.between(20:00,23:59) # From 20:00 to 23:59 for every day

我很难找到这方面的文档。我想知道时间、月份、日期和年份的 .between() 的正确语法。 感谢您的帮助

【问题讨论】:

  • 您只想要使用.between 的解决方案吗?还有其他使用掩码和切片的方法比.between
  • 是的,我对使用蒙版和切片很感兴趣。我不熟悉这个概念,但肯定很感兴趣。

标签: python pandas


【解决方案1】:

您可以使用布尔掩码来过滤 pandas 数据框,它看起来像这样:

import numpy as np
import pandas as pd

# creating random date ranging across many years
df = pd.DataFrame(np.random.random((1000,3)))
df['date'] = pd.date_range('2000-1-1', periods=1000, freq='D')

# Creating the boolean mask to keep everything from June to August
mask = (df['date'].dt.month > 6) & (df['date'].dt.month <= 8)

# Applying the boolean mask to the data frame an printing it
print(df.loc[mask])

蒙版创建可以嵌入到过滤步骤中,因此在您的情况下,解决方案是单线

only_summer_data = df.loc[(df['date'].dt.month >= 6) & (df['date'].dt.month <= 8))

如果您也想度过美好的一天,我们会得到以下信息:

start_mask = ((df['date'].dt.month == 6) & (df['date'].dt.day >= 15)) | (df['date'].dt.month > 6)

end_mask = ((df['date'].dt.month == 8) & (df['date'].dt.day <= 15)) | (df['date'].dt.month < 8)

mask = start_mask & end_mask
print(df.loc[mask])

但是,由于对日期过滤的控制更加精细,布尔掩码解决方案可能会变得非常冗长。

【讨论】:

  • 它如何知道要过滤 6 月/9 月 15 日/15 日?
  • 您可以简单地再添加两个条件来检查月份是 == 6 还是 8 以及日期是大于还是小于 15。掩码将包含 4 个条件。
  • ((df['date'].dt.month == 6 &amp; df['date].dt.day &gt; 15) | (df['date'].dt.month &gt; 6) )&amp; etc...
  • 但无论年份如何,从 6 月 15 日开始的每个月都将 > 15?
【解决方案2】:

我会将其分为 3 个更简单的条件

df = pd.DataFrame({'date': pd.date_range(start='1/1/2016', end='1/08/2018')})

select_month78 = df.date.dt.month.between(7,8)
select_month6 = (df.date.dt.month==6) & (df.date.dt.day >= 15)
select_month9 = (df.date.dt.month==9) & (df.date.dt.day <= 15)

df['is_summer'] = select_month78 | select_month6 | select_month9

df[df.is_summer]

输出:

          date  is_summer
166 2016-06-15       True
167 2016-06-16       True
168 2016-06-17       True
169 2016-06-18       True
170 2016-06-19       True
..         ...        ...
619 2017-09-11       True
620 2017-09-12       True
621 2017-09-13       True
622 2017-09-14       True
623 2017-09-15       True

[186 rows x 2 columns]

【讨论】:

    【解决方案3】:

    使用dayofyear 组件来定义范围并进行比较 - 这将允许您将过滤器限制在一个日期范围内,而不考虑年份。

    >>> start = pd.to_datetime('06-15-2000').dayofyear
    >>> end = pd.to_datetime('09-15-2000').dayofyear
    >>> start,end
    (167, 259)
    >>> df = pd.DataFrame(pd.date_range('2010-01-01', periods=52, freq='SM'),columns=['Date'])
    >>> df[(df['Date'].dt.dayofyear >= start) & (df['Date'].dt.dayofyear <= end)]
             Date
    11 2010-06-30
    12 2010-07-15
    13 2010-07-31
    14 2010-08-15
    15 2010-08-31
    16 2010-09-15
    35 2011-06-30
    36 2011-07-15
    37 2011-07-31
    38 2011-08-15
    39 2011-08-31
    40 2011-09-15
    >>> 
    

    或者

    >>> df.loc[df['Date'].dt.dayofyear.between(start,end)]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-08-08
      • 1970-01-01
      • 2014-11-30
      • 2021-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多