【问题标题】:Covert Date Range to Numpy Array as part of Groupby in Pandas将日期范围转换为 Numpy 数组作为 Pandas 中 Groupby 的一部分
【发布时间】:2017-04-16 11:28:17
【问题描述】:

我有一个从具有三列的数据库查询的Pandas dataframe。开始日期、结束日期和人员。这些数据可能没有多大意义,只是一个简化的例子。

    startdate     enddate person
0  2016-01-01  2016-01-02      A
1  2016-01-03  2016-01-03      A
2  2016-01-01  2016-01-01      B
3  2016-01-02  2016-01-02      B

在给定的日期范围内,我想知道我的dataframe 中每个人的条目涵盖了哪些日子。我的想法是创建一个长度等于该范围内天数的numpy array。如果该特定日期在该范围内,则数组中该索引的值设置为 1,否则设置为 0。然后我可以使用 groupbylambda 函数进行展平。

所以给定上述数据框,日期范围为2016-01-012016-01-03,最终结果将是:

       date_binary
person            
A        [1, 1, 1]
B        [1, 1, 0]

我已经能够计算出一些代码(groupby 部分),但不确定如何从日期范围转到数组。所以在下面的完整示例中,我只是对转换后的数据帧进行了硬编码。我想,我可以就问题所在的部分提出一个更简单的问题,但我知道Pandas 通常有一种非常紧凑的方式来做事,所以我什至发布了工作部分。

import pandas as pd
from datetime import datetime
import numpy as np
# initial dataset
df = pd.DataFrame(data=[['2016-01-01', '2016-01-02', 'A'],
                        ['2016-01-03', '2016-01-03', 'A'],
                        ['2016-01-01', '2016-01-01', 'B'],
                        ['2016-01-02', '2016-01-02', 'B']],
                  columns=['startdate', 'enddate', 'person'])

# convert columns to dates
df['startdate']= pd.to_datetime(df['startdate'],  format='%Y-%m-%d')
df['enddate']= pd.to_datetime(df['enddate'],  format='%Y-%m-%d')

# define period for which the matrix should be created
start_date = datetime(month=01, day=1, year=2016)
end_date = datetime(month=1, day=10, year=2016)


######################
# Unsure how to do this 
#####################

# what the dataframe should look like
df = pd.DataFrame(data=[[[1, 1, 0], 'A'],
                         [[0, 0, 1], 'A'],
                         [[1, 0, 0], 'B'],
                         [[0, 1, 0], 'B']],
                  columns=['date_binary', 'person'])

# flatten by person
df = df.groupby('person').aggregate(lambda x: tuple(x))

# take the max value
df.date_binary = df.date_binary.apply(lambda x: np.array([max(i) for i in zip(*x)]))

print df

【问题讨论】:

    标签: python arrays python-2.7 pandas numpy


    【解决方案1】:

    我认为您可以通过 date_range 使用 reindex 自定义函数 apply 并返回 new_indexindexer。最后需要将indexer-1 替换为01 的另一个值替换为numpy.where

    # define period for which the matrix should be created
    start_date = datetime(month=1, day=1, year=2016)
    end_date = datetime(month=1, day=3, year=2016)
    
    dr = pd.date_range(start_date, end_date) 
    
    def f(x):
        arr = pd.date_range(x.startdate, x.enddate).reindex(dr)[1]
        return pd.Series([np.where(arr == -1, 0, 1)])
    
    df['date_binary'] = df.apply(f, axis=1)
    df = df[['date_binary', 'person']]
    print (df)
      date_binary person
    0   [1, 1, 0]      A
    1   [0, 0, 1]      A
    2   [1, 0, 0]      B
    3   [0, 1, 0]      B
    

    【讨论】:

    • 感谢这是一个不错的解决方案。你能解释一下np.where(arr == -1, 0, 1) 在做什么吗?
    • numpy where is simple if condition is True then 0 else 1. 这里索引器返回 -1 如果缺少值 - 你需要 0 和其他值需要 1
    • 当我打印arr 时,数组的第一行是[ 0 1 -1]。由于这对应于['2016-01-01', '2016-01-02', 'A'],不应该是[1, 1, -1],因为我们有两个匹配项,那么一天超出范围?也许我不明白那段代码在做什么。
    • 我明白-1 表示缺少值,如果012 它是第一个数组的值索引
    猜你喜欢
    • 1970-01-01
    • 2018-03-03
    • 1970-01-01
    • 2017-02-11
    • 2013-08-11
    • 1970-01-01
    • 1970-01-01
    • 2017-01-12
    • 1970-01-01
    相关资源
    最近更新 更多