首页 > 解决方案 > Pandas:基于现有行的新行

问题描述

df我有一个具有以下结构的 Pandas 数据框:dataId, nodeId, tickDatetime

该数据集表示时间 ( tickDatetime),其中元素 ( dataId) 通过节点 ( nodeId)。

这是一个例子:

           dataId    nodeId     tickDatetime
0          data-0   node-01             3000
1          data-0   node-02             5000    
2          data-1   node-02             4000    
3          data-1   node-01             6000    
4          data-0   node-01             8000    
5          data-0   node-00            10000    
...           ...       ...  

从这个数据框中,我想创建一个新的数据框routes,其中包含节点序列和每个dataId.

所以我做了以下事情:

routes = df.sort_values('tickDatetime').groupby('dataId').agg({'nodeId':[lambda x: list(x)],'tickDatetime':lambda x: list(x)})

def datetimes_to_travel_times(datetimes):
    traveltimes = np.empty(len(datetimes))
    old_value = datetimes[0]
    traveltimes[0] = 0

    for i in range(1,len(datetimes)):
        traveltimes[i] = datetimes[i] - old_value
        old_value = datetimes[i]

    return traveltimes

routes['traveltimes'] = routes['tickDatetime'].apply(lambda row: datetimes_to_travel_times(row))

这给了我预期的输出(也许不是最好的方法?):

           dataId                              nodeId                tickDatetime           traveltimes
0          data-0   [node-01,node-02,node-01,node-00]      [3000,5000,8000,10000]    [0,2000,3000,2000]
1          data-1                   [node-02,node-01]                 [4000,6000]              [0,2000]

现在,如果旅行时间超过某个阈值,我希望我的路线被拆分。

例如,阈值为 3000,我希望我的routes数据框看起来像这样:

           dataId   routeId              nodeId    tickDatetime    traveltimes
0          data-0         0   [node-01,node-02]      [3000,5000]      [0,2000]
1          data-0         1   [node-01,node-00]     [8000,10000]      [0,2000]
2          data-1         0   [node-02,node-01]      [4000,6000]      [0,2000]

如何使用 Pandas 实现这一目标?


编辑 :

我设法解决了我的问题:

def split_routes(row):
    threshold = 3000
    nodes = row['nodeId']
    traveltimes = row['traveltimes']

    rows = []
    route_id = 0
    route_nodes = []
    route_traveltimes = []
    for i in range(0, len(traveltimes)):
        if(traveltimes[i]<threshold):
            route_nodes.append(nodes[i])
            route_traveltimes.append(traveltimes[i])
        else : 
            # Route route_id completed, starting a new one
            row['route_id'] = route_id
            row['Reader'] = route_nodes
            row['traveltimes'] = route_traveltimes
            rows.append(row)
            route_id+=1
            route_nodes.append(nodes[i])
            route_traveltimes.append(0)  

    # Route route_id completed, starting a new one            
    row['route_id'] = route_id
    row['Reader'] = route_nodes
    row['traveltimes'] = route_traveltimes
    rows.append(row)

    return pd.DataFrame(rows)

splitted_routes_array = []
for index, row in routes.iterrows():
    splitted_routes_array.append(split_routes(row))

splitted_routes = pd.concat(splitted_routes_array)

标签: pythonpandas

解决方案


df = pd.DataFrame({
'dataId':['data-0','data-0','data-1','data-1','data-0','data-0'],
'nodeId':['node-01','node-02','node-02','node-01','node-01','node-00'],
'tickDatetime':[3000,5000,4000,6000,8000,10000]})

append_ = lambda x:list(x)

df_2 = pd.DataFrame()
df_2['nodeId'] = df.groupby('dataId')['nodeId'].apply(append_)
df_2['tickDatetime'] = df.groupby('dataId')['tickDatetime'].apply(append_)
print(df_2)

输出:

                                  nodeId               tickDatetime
dataId                                                                 
data-0  [node-01, node-02, node-01, node-00]  [3000, 5000, 8000, 10000]
data-1                    [node-02, node-01]               [4000, 6000]

推荐阅读