为什么这个任务在 Python 中比 Julia 更快?

Mar*_*nus 7 python performance r julia

我在 RStudio 中运行了以下代码:

exo <- read.csv('exoplanets.csv',TRUE,",")
df <- data.frame(exo)

ranks <- 570
files <- 3198
datas <- vector()

for ( w in 2:files ) {
    listas <-vector()
    for ( i in 1:ranks) {
            name <- as.character(df[i,w])
            listas <- append (listas, name)
    }
    datas <- append (datas, listas)
}
Run Code Online (Sandbox Code Playgroud)

它读取一个巨大的 NASA CSV 文件,将其转换为数据帧,将每个元素转换为字符串,并将它们添加到向量中。

RStudio 花费了 4 分 15 秒。

所以我决定在 Julia 中实现相同的代码。我在 VS Code 中运行了以下命令:

using CSV, DataFrames

df = CSV.read("exoplanets.csv", DataFrame)

fil, col = 570, 3198
arr = []

for i in 2:fil
        for j in 1:col
            push!(arr, string(df[i, j]))
        end
end
Run Code Online (Sandbox Code Playgroud)

结果很好。Julia 代码只用了 1 分 25 秒!

然后出于纯粹的好奇心,我这次在 Python 中实现了相同的代码来进行比较。我在 VS Code 中运行了以下命令:

import numpy as np
import pandas as pd

exo = pd.read_csv("exoplanets.csv")
arr = np.array(exo)

fil, col = 570, 3198
lis = []

for i in range(1, fil):
        for j in range(col):
            lis.append(arr[i][j].astype('str'))
Run Code Online (Sandbox Code Playgroud)

结果让我震惊了!只有35秒!!!而在 Anaconda 的 Spyder 中只需 26 秒!!!近200万漂浮!!!Julia 在数据分析方面比 Python 慢吗?我可以改进 Julia 代码吗?

Bog*_*ski 10

这取决于您想要测试的内容(即,如果您想测试循环还是只想快速获得结果)。我假设您希望以干净的代码快速获得结果,在这种情况下,我将在 Julia 中按以下方式编写此操作:

arr = reduce(vcat, eachrow(Matrix(string.(df[2:570, 1:3198]))))
Run Code Online (Sandbox Code Playgroud)

您能否确认这会产生预期结果以及此操作的时间安排是什么?(在此,我假设您的行数超过 570,列数超过 3198,所以我首先对它们进行子集化)

如果您想测试循环,那么您答案下的评论将开始相关。

另请注意,您的 DataFrames.jl 代码不会执行与 R 和 Python 中的代码相同的操作(循环顺序不同,因此请您仔细检查您需要的内容)。这种差异对于性能至关重要。我已经为您提供了重现 DataFrames.jl 代码行为的代码(与 R/Python 代码相比,这是您想要执行的操作的更难/更慢的变体)

  • 是的 - 它更慢,因为它执行的操作与 @phipsgabler 的解决方案不同。在我的回答中,我复制了您的 Julia 代码。phipsgabler 复制了 Python 代码。出于好奇 - phipsgabler 对您的数据的解决方案的速度是多少(进行比较)? (2认同)

phi*_*ler 8

注意:我编写下面的内容时假设您想要其他列顺序(如 Python 和 R 示例中所示)。这种方式在 Julia 中效率更高;为了使其与您原来的行为等效,请在正确的位置排列逻辑或数据(留下作为练习)。Bogumi\xc5\x82 的答案已经做了正确的事情。

\n
\n

将内容放入函数中,尽可能预分配,按步幅顺序迭代,使用视图,并使用内置函数和广播:

\n
function tostringvector(d)\n    r, c = size(d)\n    result = Vector{String}(undef, r*c)\n    v = reshape(result, r, c)\n    for (rcol, dcol) in zip(eachcol(v), eachcol(d))\n        @inbounds rcol .= string.(dcol)\n    end\n    return result\nend\n
Run Code Online (Sandbox Code Playgroud)\n

这当然可以更努力地优化。

\n

或者更简单地说,利用DataFrames已经提供的内容:

\n
tostringvector(d) = vec(Matrix(string.(d)))\n
Run Code Online (Sandbox Code Playgroud)\n

  • 在OP问题中,数据应该按行收集(这是在DataFrames.jl变体中所做的)而不是按列收集(它是在代码的R/Python变体中按列收集)。您出色的答案显示了差异 - 您的代码将比我的更快,因为您按列而不是按行。 (2认同)
  • 该死的专栏订单!:DI 应该更加想知道为什么你使用 `reduce(vcat,..)`。 (2认同)
  • 你的意思是`CSV.read("exoplanets.csv", DataFrame)`很慢?原因很可能是编译成本。如果您有同质数据并且希望避免支付编译成本,请使用“DelimitedFiles”模块。编译后 CSV 比 pandas 更快,特别是对于大数据,请参阅 https://juliacomputing.com/blog/2020/06/fast-csv/。请注意,编译是一次性成本(当您再次运行代码时,它应该运行得更快) (2认同)

Ant*_*llo 5

鉴于您对 @phipsgabler 答案的评论,您在这里计时的是导入模块和编译的固定成本,而不是任务本身。