python - Pandas:应用返回多行多列的函数
问题描述
我有一个routes
具有以下结构的 DataFrame:
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
同时返回多行和多列。
有人可以给我一些提示吗?
解决方案
要在 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]
推荐阅读
- python - Pandas Groupby 在不同轴上使用多个标准
- php - 如何通过 PHP 将网站中的整个数字替换为波斯数字?
- javascript - 因为我的动态标题显示不正确?
- html - Bootstrap 导航栏显示问题
- mysql - rsyslog ommysql 按优先级过滤
- c++ - 最近点算法 | 如何改进它?
- asynchronous - 如何在ansible中使用包含并行化循环
- git - 无法访问 microsoft azure devops 页面中的 Repo 选项
- batch-file - 使用延迟扩展转义感叹号
- keras - 如何使用 keras 在 CNN 中同时获得最佳 val_acc 和 val_loss?