我有一个如下所示的数据列,其中缺少一些日期。
obstime
2012-01-01
2012-01-02
2012-01-03
2012-01-04
....
2016-12-28
2016-12-29
2016-12-30
2016-12-31
答案 0 :(得分:0)
使用:
#sample data
df = pd.DataFrame({'obstime':pd.date_range('2012-01-01', '2016-12-31')})
removed = ['2013-09-01', '2013-09-02', '2013-09-03','2014-10-09','2016-12-30']
removed1 = pd.date_range('2016-12-16', '2016-12-22')
removed2 = pd.date_range('2016-10-10', '2016-12-03')
df = df[~df['obstime'].isin(pd.to_datetime(removed).append(removed1).append(removed2))]
#print (df)
#add missing values
df1 = df.set_index('obstime', drop=False).reindex(pd.date_range('2012-01-01', '2016-12-31'))
#create mask for start and end missing values and for start and end months with NaT
m = df1['obstime'].isnull()
start_NaT = m.ne(m.shift())
end_NaT = m.ne(m.shift(-1))
start_months = df1.index.day == 1
end_months = df1.index.isin(df1.index + pd.offsets.MonthEnd(0))
mask = (start_NaT | end_NaT | start_months | end_months) & m
#mask for separated missing values
s = start_NaT.cumsum()
m1 = s.map(s.value_counts()) == 1
#for start and end days join -
df2 = df1[mask & ~m1].reset_index().rename(columns={'index':'date'})
df2['day'] = df2['date'].dt.day.astype(str)
df2 = df2.groupby(np.arange(len(df2.index)) // 2).agg({'date':'first', 'day':'-'.join})
#separate days
df3 = df1[mask & m1].copy()
df3['day'] = df3.index.day.astype(str)
#join together
df3 = pd.concat([df2.set_index('date'), df3])
#join days by , add missing months and years
df4 = (df3.groupby([df3.index.month, df3.index.year])['day']
.agg(','.join)
.unstack(fill_value='yes')
.reindex(index=range(1, 13), columns=range(2008, 2017),fill_value='yes'))
print (df4)
2008 2009 2010 2011 2012 2013 2014 2015 2016
1 yes yes yes yes yes yes yes yes yes
2 yes yes yes yes yes yes yes yes yes
3 yes yes yes yes yes yes yes yes yes
4 yes yes yes yes yes yes yes yes yes
5 yes yes yes yes yes yes yes yes yes
6 yes yes yes yes yes yes yes yes yes
7 yes yes yes yes yes yes yes yes yes
8 yes yes yes yes yes yes yes yes yes
9 yes yes yes yes yes 1-3 yes yes yes
10 yes yes yes yes yes yes 9 yes 10-31
11 yes yes yes yes yes yes yes yes 1-30
12 yes yes yes yes yes yes yes yes 1-3,16-22,30
答案 1 :(得分:0)
我的解决方案基于熊猫,无需使用任何数据库。
该想法是使用“完整”索引(使用 年份范围内的所有日期)。为此测试,我使用了日期 从2016年和2017年开始。
然后,我们仅保留“刚刚添加”的行,并带有“不存在”测量的日期。
其余操作为:
因此整个脚本可以如下:
import pandas as pd
import calendar
# Function to be applied to date groups for each month
def fun(x):
dt = x.result
day = pd.Timedelta('1d')
startDates = dt[dt.diff() != day]
if startDates.size > 0:
endDates = dt[(dt - dt.shift(-1)).abs() != day]
return '&'.join([(f'{s.day}-{e.day}') for s, e in zip(startDates, endDates)])
else:
return 'OK'
# Source dates
dates = pd.date_range('2016-01-01', '2016-01-13')\
.append(pd.date_range('2016-01-20', '2016-01-29'))\
.append(pd.date_range('2016-02-10', '2016-02-20'))\
.append(pd.date_range('2016-03-11', '2017-11-20'))\
.append(pd.date_range('2017-11-25', '2017-12-31'))
# Source DataFrame with random results for dates given
df = pd.DataFrame(data={ 'result': np.random.randint(10, 30, len(dates))},
index=dates)
# Index for full range of dates
idxFull = pd.date_range('2016-01-01', '2017-12-31')
# "Expand" to all dates
df2 = df.reindex(idxFull)
# Leave only "empty" rows
df2.drop(df2[df2.result.notna()].index, inplace=True)
# Copy index to result
df2.result = df2.index
# Group by months
gr = df2.groupby(pd.Grouper(freq='M'))
# Result - Series
res = gr.apply(fun)
# Result - DataFrame with year/month "extracted" from date
res2 = pd.DataFrame(data={'res': res, 'year': res.index.year,
'month': res.index.month })
# Result - pivot'ed res2
res3 = res2.pivot(index='month', columns='year').fillna('OK')
# Add month names
res3['MonthName'] = list(calendar.month_name)[1:]
# Set month names as index
res3.set_index('MonthName', inplace=True)
当您print(res3)
时,结果为:
res
year 2016 2017
MonthName
January 14-19&30-31 OK
February 1-9&21-29 OK
March 1-10 OK
April OK OK
May OK OK
June OK OK
July OK OK
August OK OK
September OK OK
October OK OK
November OK 21-24
December OK OK