Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/355.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 熊猫根据日期合并行_Python_Pandas - Fatal编程技术网

Python 熊猫根据日期合并行

Python 熊猫根据日期合并行,python,pandas,Python,Pandas,我有一个客户数据框架,其中包含他们收到的发货记录。不幸的是,这些可能重叠。我试图减少行数,以便可以看到连续使用的日期。除了蛮力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

我有一个客户数据框架,其中包含他们收到的发货记录。不幸的是,这些可能重叠。我试图减少行数,以便可以看到连续使用的日期。除了蛮力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

reductionFunction将前3条记录分组为一条,因为在每种情况下,下一条记录的开始日期都在前一条记录的结束日期之前。我基本上是将多个重叠的记录转换成一个记录


关于一个好的“pythonic”实现的想法?我可以在每个小组内做一个讨厌的while循环,但我不想

从根本上说,我认为这是一个图连通性问题:解决这个问题的一个快速方法是某种形式的图连通性算法。熊猫不包括这样的工具,但是。您可以使用scipy中的压缩稀疏图(
csgraph
)子模块来解决以下问题:

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')
从scipy.sparse.csgraph导入连接的\u组件
#转换为datetime,使min()和max()起作用
df.startDate=pd.to_datetime(df.startDate)
df.endDate=pd.to_datetime(df.endDate)
def还原功能(数据):
#创建日期范围之间连接的二维图形
开始=data.startDate.values
end=data.endDate.values
图形=(开始=开始[:,无])
#在此图中查找连接的组件
n_组件,索引=连接的_组件(图)
#按这些连接的组件对结果进行分组
返回数据.groupby(index).aggregate({'startDate':'min',
“结束日期”:“最大值”,
“shipNo”:“first”})
df.groupby(['Cust'])。apply(reductionFunction)。reset_index('Cust'))

如果您想从这里对
shipNo
做一些不同的事情,那么应该非常简单


请注意,上面的函数不是蛮力,而是使用a来查找连接。

如果您愿意使用辅助数据框来保存结果,老实说,您可以在所有行中循环

from time import strptime

results = [df.iloc[0]]

for i, (_, current_row) in enumerate(df1.iterrows()):
    try:
        next_row = df.iloc[i+1]        
        if strptime(current_row['endDate'], '%Y-%M-%d') < strptime(next_row['startDate'], '%Y-%M-%d'):
            results[-1]['endDate'] = current_row['endDate']
            results.append(next_row)
    except IndexError:
        pass

print pd.DataFrame(results).reset_index(drop=True)
从时间导入strtime
结果=[df.iloc[0]]
对于i,枚举(df1.iterrows())中的(u,当前_行):
尝试:
下一行=df.iloc[i+1]
如果strtime(当前行['endDate'],'%Y-%M-%d')
这个问题不完全相同,但很相似:答案可能是相关的。谢谢您的输入!我没有考虑过这种方法。您的解决方案适用于仅列出一个客户的示例数据。但是,它不适用于我的实际示例,其中有多个Cust值。修改df使其包含一个“B”cust,如df.ix[4]=['B'、'2011-02-07'、'2011-02-22',1]会破坏解决方案。有没有想过如何让它更通用于多个客户?我不熟悉那个特殊的scipy图形函数。在添加第二个客户后,解决方案对我有效。。。您得到了什么错误?ValueError:数据、索引和indptr应该是1-DI在Pandas 0.17和Scipy 0.16上看不到该错误。您使用的是什么版本?如果您使用的是SciPy 0.14或更高版本,则可能与此错误有关:感谢您的输入,我知道我可以通过对所有行的iterrows()调用进行暴力攻击,但我正在像瘟疫一样与之斗争。结果将被实时调用,并且需要有一些响应的外观。我已经有了一个iterrows()实现,它比我想要的要慢。@flyingmeatball干杯,我只想把这个hear留给我自己参考
from time import strptime

results = [df.iloc[0]]

for i, (_, current_row) in enumerate(df1.iterrows()):
    try:
        next_row = df.iloc[i+1]        
        if strptime(current_row['endDate'], '%Y-%M-%d') < strptime(next_row['startDate'], '%Y-%M-%d'):
            results[-1]['endDate'] = current_row['endDate']
            results.append(next_row)
    except IndexError:
        pass

print pd.DataFrame(results).reset_index(drop=True)