У меня есть Pandas
dataframe
запрос из базы данных, содержащей три столбца. Дата начала, дата окончания и лицо. Данные могут не иметь большого смысла, но это просто упрощенный пример.Скрытый диапазон дат для массива Numpy в составе Groupby в Pandas
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. Затем я сглаживаю функцию groupby
и lambda
.
Итак, учитывая выше dataframe и диапазон дат 2016-01-01
до 2016-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
спасибо это хорошее решение. Можете ли вы объяснить, что делает 'np.where (arr == -1, 0, 1)'? – user2242044
numpy где is simple, если условие True, то 0 else 1. И здесь indexer возвращает '-1', если значение отсутствует - вам нужно' 0', а для других значений нужно '1' – jezrael
, когда я печатаю' arr' первую строку массив равен '[0 1 -1]'. Поскольку это соответствует '['2016-01-01', '2016-01-02', 'A']', не должно быть '[1, 1, -1]', поскольку у нас есть два совпадения, тогда день за пределами диапазона? Может быть, я не понимаю, что делает этот код. – user2242044