是我太菜了,还是 pandans 就是这么慢

2024-06-06 22:00:36 +08:00
 jianghu52

thinkpad T14 的机器,i7 的 cup ,32G 内存。 我有两个 excel ,一个 4 千行,6 列 名字叫 tb4k ,一个 6 千行,10 列,名字叫 tb6k 。 都用 pandas 接成 df 对象,然后循环两个 df 。最后保存成 excel 。

伪代码 遍历 tb4k 的每一行,取前三列的内容: 遍历 tb6k: tb6k 的前三列一致: 将 tb6k 的后面第 5,8,10 行的内容赋值给 tb4k 的后三列 停止遍历 tb6k 保存 tb4k 到原 excel

我执行段代码。tb4k 遍历每一行大概需要 1s 左右(包含 tb6k 的遍历)。导致我运行这段程序要接近 1 小时。 这速度也太慢了吧。还是我水平太菜了,没有用好 pandas ?

5068 次点击
所在节点    Python
41 条回复
ipwx
2024-06-07 12:40:20 +08:00
说错了 100 多万行的 1 分钟数据。
Sawyerhou
2024-06-07 12:41:05 +08:00
加 3 个辅助列 tb6k shift -5,-8,-10 ,将 tb4k 和 tb6k 的前 3 列设为 multiIndex ,然后 loc 拼接。
目测你这个前三列应该没重复的,如果有,如楼上说用 join 替代 loc 。

不要循环,用矩阵运算,1s 都用不了。
datou06415
2024-06-07 13:07:49 +08:00
6 千行的数据的话,以你的机器配置,直接用 DataFrame 的 read_excel() 把 excel 数据读进来再处理都行,避免一行行的读文件。如果文件非常多行,再考虑分批次处理。

想知道运行慢的具体原因,上 cProfile ,或者粗暴点,日志记录关键操作位置的起始时间。总之,性能调优,先上工具测量指标。
cogitoxin
2024-06-07 13:44:25 +08:00
polars 你值得拥有
Rorysky
2024-06-07 14:05:43 +08:00
都放内存里,哪儿来这么多的时间
jZEdn7k4
2024-06-07 14:08:49 +08:00
这个速度真是你代码太菜的问题。。。
dbak
2024-06-07 14:11:01 +08:00
pandas 有矢量化操作矩阵数据 你小子用的 for 循环吧
zealotxxxx
2024-06-07 14:28:17 +08:00
只能说是太菜,如果不是学习,你的需求建议用 excel

另外,你 tb4k 直接走 df.loc 或者 ilock 都行,如果你用 loop 也只需要执行 4k 次。

但是你如果数据唯一,完全可以走 join ,然后直接取要拿的列就行了
zealotxxxx
2024-06-07 14:30:22 +08:00
你不会是嵌套 loop 吧?

4000 * 6000 = 2400 万次? 那不慢才怪
psyer
2024-06-07 14:32:46 +08:00
看下代码呢
weidaizi
2024-06-07 14:52:44 +08:00
看了一下,这慢很正常呀,帮大家格式化一下楼主的伪代码:
```
for _, row_tb4k in df_tb4k.iterrows():
for _, row_tb6k in df_tb6k.iterrows():
if row_tb4k["c1"] == row_tb6k["c1"] and row_tb4k["c2"] == row_tb6k["c2"] and row_tb4k["c3"] == row_tb6k["c3"]:
row_tb4k["c4“] = row_tb6k["c5"]
row_tb4k["c5“] = row_tb6k["c8"]
row_tb4k["c6“] = row_tb6k["c10"]
```

* 首先,都用了 pandas 了,为啥手动遍历来合并?
* 其次,即使徒手写,也需要建个索引来做呀,你这时间复杂度是 O(n^2) 了
weidaizi
2024-06-07 14:56:56 +08:00
@weidaizi = = 我晕,前面的空格没了
encro
2024-06-07 15:03:56 +08:00
我用 pandas 计算 k 线指标,1 万跟 k 线,几十个指标也只要几秒钟。估计你用的 pandans 和我用的 pandas 不是一个东西。
billbur
2024-06-07 15:05:50 +08:00
djangovcps
2024-06-07 15:22:09 +08:00
感觉你笛卡尔积的循环了,要不嗯循环几千行不肯能一小时
kingbill
2024-06-07 15:34:35 +08:00
我觉得是 T14 的锅,是 U 结尾的 i7 吗?
stiangao
2024-06-07 16:47:57 +08:00
前三列一样就合并一行的内容吧,

按你的思路要遍历 4000*6000=2400w 次,那确实慢,

按这个方法写,遍历一次 6000 行,前三列拼一个 key, 后三列拼 value ,生成一个 dict,
遍历 4000 行的文件,从 dict 里查, 查到了就拼接,
总共遍历数据 1w 次
winglight2016
2024-06-07 16:51:40 +08:00
太菜了,pandas 用成了 array

另外,两个单词都拼错了,看着难受┑( ̄Д  ̄)┍
henix
2024-06-07 17:42:44 +08:00
遍历 6000 行的 df 需要 1s 也太慢。你用没用 df.iterrows 遍历? iterrows 跟整数索引( for i in range(len(df)))的性能差别挺大的。
一点建议:为啥非要用 excel 和 pandas ?因为 excel 不是文本格式,不方便程序处理。pandas 个人认为对初学者来说有很多坑。
一个架构上的建议:先将你这两个 excel 另存为 csv 格式,然后用 Python 自带的 https://docs.python.org/zh-cn/3/library/csv.html 把每个文件读进来存成一个 list ,算法跟你现在的保持不变,说不定都比你现在的方式快。
Laysan
2024-06-07 21:50:50 +08:00
show your code

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1047504

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX