2017-02-26 7 views
2

Ich mag ‚B‘ von Terminen Daten in ‚A‘ subtrahieren und die Differenz der Tage für jeden Monat zwischen den Daten erhalten:Wie kann ich berechnen Tage zwischen zwei in Tage pro Monat getrennt Daten in Pandas

df 
     A  B 
2014-01-01 2014-02-28 
2014-02-03 2014-03-01 

df['A'] = pd.to_datetime(df['A']) 
df['B'] = pd.to_datetime(df['B']) 
#df['A'] - df['B'] 

Desired Output: 
================= 
01(Jan) 02(Feb)  03(Mar) 
================================ 
31days  28days  0days 
0days  26days  1day  

Wie kann dies mit Pandas erreicht werden?

Antwort

1

Interessantes Problem, danke für den Austausch. Die hier vorgestellte Grundidee besteht darin, eine Funktion zu erstellen, die zwischen dem Start- und Enddatum iterieren und ein Diktat mit Schlüsseln für Jahr/Monat und Werten für die Anzahl der Tage in diesem Monat zurückgeben kann.

Code:

import calendar 
import datetime as dt 

def year_month(date): 
    """ return year/month tuple from date """ 
    return date.year, date.month 

def next_year_month(date): 
    """ given a year/month tuple, return the next year/month """ 
    if date[1] == 12: 
     return date[0] + 1, 1 
    else: 
     return date[0], date[1] + 1 

def days_per_month(start_date, end_date): 
    """ return dict keyed with year/month tuples and valued with days in month """ 
    assert isinstance(start_date, (dt.datetime, dt.date)) 
    assert isinstance(end_date, (dt.datetime, dt.date)) 

    start = year_month(start_date) 
    end = year_month(end_date) 
    days_in_month = (
     calendar.monthrange(*start)[1] - start_date.day + 1) 

    result = {} 
    while start != end: 
     result[start] = days_in_month 
     start = next_year_month(start) 
     days_in_month = calendar.monthrange(*start)[1] 
    result[end] = (
     end_date.day - calendar.monthrange(*end)[1] + days_in_month) 
    return result 

Testcode:

import pandas as pd 
data = [x.strip().split() for x in """ 
     A   B 
    2014-01-01 2014-02-28 
    2014-02-03 2014-03-01 
    2014-02-03 2014-02-05 
""".split('\n')[1:-1]] 
df = pd.DataFrame(data=data[1:], columns=data[0]) 
df['A'] = pd.to_datetime(df['A']) 
df['B'] = pd.to_datetime(df['B']) 

result = pd.DataFrame.from_records(
    (days_per_month(a, b) for a, b in zip(df['A'], df['B'])) 
).fillna(0).astype(int) 

print(result) 

Ergebnisse:

(2014, 1) (2014, 2) (2014, 3) 
0   31   28   0 
1   0   26   1 
2   0   3   0 
Verwandte Themen