【问题标题】:Pandas : Apply function that returns multiple rows and columnsPandas:应用返回多行多列的函数
【发布时间】:2020-02-19 09:19:47
【问题描述】:

我有一个 DataFrame routes,其结构如下:

      id                                             nodes                            traveltimes
0   id-1                                  [node-A, node-B]                                  [6.0]
1   id-2                  [node-A, node-C, node-D, node-E]                      [4.0, 80.0, 38.0]
2   id-3                                  [node-B, node-D]                                 [90.0]
3   id-4                                          [node-A]                                     []
4   id-5  [node-A, node-B, node-C, node-D, node-E, node-D]         [35.0, 30.0, 110.0, 20.0, 5.0]
..                                                 ...                                    ...

nodes 列中的值列表是图的节点,traveltimes 列中的值是两个节点之间的时间。每一行对应图中的一个route

我想将我的routes 拆分为traveltimes 的阈值。例如,对于 70 的阈值,我想得到以下结果:

      id     route_id                            nodes                            traveltimes
0     id-1          0                 [node-A, node-B]                                  [6.0]
1     id-2          0                 [node-A, node-C]                                  [4.0]        
2     id-2          1                 [node-D, node-E]                                 [38.0]
3     id-3          0                         [node-B]                                     []
4     id-3          1                         [node-D]                                     []
5     id-4          0                         [node-A]                                     []
6     id-5          0         [node-A, node-B, node-C]                           [35.0, 30.0]
7     id-5          1         [node-D, node-E, node-D]                            [20.0, 5.0]
..                                                 ...                                    ...

我编写了以下代码来做我想做的事,但是效率很低。

我有一个分割路线的功能:

def split_routes(row):
    newrow = row.copy()

    threshold = 70

    nodes = newrow['nodes']
    traveltimes = newrow['traveltimes']

    rows = []
    route_id = 0
    route_nodes = []
    route_traveltimes = []

    route_nodes.append(nodes[0])

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

            newrow = row.copy()
            route_nodes = []
            route_traveltimes = []
            route_id+=1
            route_nodes.append(nodes[i])

    # Route route_id completed     
    newrow['route_id'] = route_id
    newrow['nodes'] = route_nodes
    newrow['traveltimes'] = route_traveltimes
    rows.append(newrow)

    df = pd.DataFrame(rows)
    return df

这就是我使用它的方式:

splitted_routes_array = []

for index, row in routes.iterrows():    # Inefficient loop
    splitted_routes_array.append(split_routes(row))

splitted_routes = pd.concat(splitted_routes_array).reset_index(drop=True)

我想我可以在不自己迭代行的情况下做一些更有效的事情。但我不知道如何使用apply 同时返回多行和多列。

有人可以给我一些提示吗?

【问题讨论】:

  • 我想这已经接近解决我的问题了。但是当我使用它时,我得到了一个奇怪的结果。 splitted_routes = routes.apply(split_routes,axis=1) 给我一个系列作为输出,其中每个元素似乎都包含一个数据框。
  • 您可以按照答案中的建议尝试使用 stack() 和 reset_index()。

标签: python pandas


【解决方案1】:

要在 pandas 中分解多个列,唯一的前提是在要分解的所有列中的列表中具有相同数量的元素。这可以通过 -

def get_nodes(x):
    if(len(x)<2):
        return []
    return [[x[i], x[i+1]] for i in range(len(x)-1)]

df['nodes'] = df['nodes'].apply(lambda x: get_nodes(x))

在此之后,可以使用 - 来展平数据 -

df = df.set_index('id').apply(lambda x: x.apply(pd.Series).stack()).reset_index().rename(columns={'level_1':'route_id'})

要找到所有旅行时间大于 70.0 的路线,我们可以简单地做 -

df[df['traveltimes']>70]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-14
    • 2014-11-01
    • 2021-10-20
    • 2019-11-26
    • 2018-06-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多