我有一个客户数据框,其中包含他们收到的货件记录.不幸的是,这些可能重叠.我正在尝试减少行数,以便我可以看到连续使用的日期.有没有什么方法可以做到这一点除了蛮力iterrows实施?
这是一个示例和我想做的事情:
df = pd.DataFrame([['A','2011-02-07','2011-02-22',1],['A','2011-02-14','2011-03-10',2],['A','2011-03-07','2011-03-15',3],['A','2011-03-18','2011-03-25',4]], columns = ['Cust','startDate','endDate','shipNo'])
df
Run Code Online (Sandbox Code Playgroud)
condensedDf = df.groupby(['Cust']).apply(reductionFunction)
condensedDF
Run Code Online (Sandbox Code Playgroud)
reductionFunction将前3个记录分组为一个,因为在每种情况下,下一个的开始日期都在前一个结束日期之前.我基本上把多个记录重叠成一条记录.
关于良好"pythonic"实施的想法?我可以在每个小组内做一个讨厌的循环,但我不想......
从根本上说,我认为这是一个图形连接问题:解决它的一种快速方法将是某种图形连接算法.熊猫不包括这样的工具,但scipy确实如此.您可以使用csgraph
scipy中的压缩稀疏图()子模块来解决您的问题,如下所示:
from scipy.sparse.csgraph import connected_components
# convert to datetime, so min() and max() work
df.startDate = pd.to_datetime(df.startDate)
df.endDate = pd.to_datetime(df.endDate)
def reductionFunction(data):
# create a 2D graph of connectivity between date ranges
start = data.startDate.values
end = data.endDate.values
graph = (start <= end[:, None]) & (end >= start[:, None])
# find connected components in this graph
n_components, indices = connected_components(graph)
# group the results by these connected components
return data.groupby(indices).aggregate({'startDate': 'min',
'endDate': 'max',
'shipNo': 'first'})
df.groupby(['Cust']).apply(reductionFunction).reset_index('Cust')
Run Code Online (Sandbox Code Playgroud)
如果你想shipNo
从这里做一些不同的事情,它应该非常简单.
请注意,connected_components()
上面的函数不是暴力,而是使用快速算法来查找连接.