检查一行中的所有值是否相同或缺失的最有效方法

هنر*_*تان 5 r filter julia dplyr data.table

我最初在论坛中提出这个问题data.table,并收到了一些很好的答案,但我希望找到一个不到一秒的解决方案(真实数据暗淡 3M x 303)

\n

我在 R 社区中的帖子以及 julia 中的 MWE 的链接(使用 DataFrames.jl 如果我使用了错误的包,请告诉我)

\n
julia> using DataFrames\n\njulia> df = DataFrame(v1 = [1.0,2.1,3.0], v2 = [1,3,3], v3 = [missing,2.1,3.0])\n3\xc3\x973 DataFrame\n Row \xe2\x94\x82 v1       v2     v3\n     \xe2\x94\x82 Float64  Int64  Float64?\n\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\xbc\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80\n   1 \xe2\x94\x82     1.0      1  missing\n   2 \xe2\x94\x82     2.1      3        2.1\n   3 \xe2\x94\x82     3.0      3        3.0\n\njulia> desired = [true,false,true]\n3-element Vector{Bool}:\n 1\n 0\n 1\n
Run Code Online (Sandbox Code Playgroud)\n

Bog*_*ski 9

在 Julia 中,与 R 类似,使用矩阵进行此类运算也是很自然的:

\n
julia> using BenchmarkTools\n\njulia> function helper(x)\n           nonempty = false\n           local fv\n           for v in x\n               if !ismissing(v)\n                   if nonempty\n                       v == fv || return false\n                   else\n                       fv = v\n                       nonempty = true\n                   end\n               end\n           end\n           return true\n       end\nhelper (generic function with 1 method)\n\njulia> mat = rand([1, 2, missing], 3_000_000, 303);\n\njulia> @benchmark helper.(eachrow($mat))\nBenchmarkTools.Trial: 34 samples with 1 evaluation.\n Range (min \xe2\x80\xa6 max):  139.440 ms \xe2\x80\xa6 154.628 ms  \xe2\x94\x8a GC (min \xe2\x80\xa6 max): 5.74% \xe2\x80\xa6 5.15%\n Time  (median):     147.890 ms               \xe2\x94\x8a GC (median):    5.27%        \n Time  (mean \xc2\xb1 \xcf\x83):   147.876 ms \xc2\xb1   3.114 ms  \xe2\x94\x8a GC (mean \xc2\xb1 \xcf\x83):  5.23% \xc2\xb1 0.95%\n\n                    \xe2\x96\x83    \xe2\x96\x83   \xe2\x96\x83  \xe2\x96\x83  \xe2\x96\x88\xe2\x96\x88 \xe2\x96\x83\n  \xe2\x96\x87\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x87\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x88\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x88\xe2\x96\x87\xe2\x96\x87\xe2\x96\x87\xe2\x96\x88\xe2\x96\x81\xe2\x96\x81\xe2\x96\x88\xe2\x96\x87\xe2\x96\x81\xe2\x96\x88\xe2\x96\x88\xe2\x96\x87\xe2\x96\x88\xe2\x96\x81\xe2\x96\x87\xe2\x96\x81\xe2\x96\x87\xe2\x96\x87\xe2\x96\x81\xe2\x96\x87\xe2\x96\x87\xe2\x96\x81\xe2\x96\x87\xe2\x96\x81\xe2\x96\x87\xe2\x96\x87\xe2\x96\x87\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x87\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x87 \xe2\x96\x81\n  139 ms           Histogram: frequency by time          155 ms <\n\n Memory estimate: 114.80 MiB, allocs estimate: 6.\n
Run Code Online (Sandbox Code Playgroud)\n

该操作也可以在 DataFrames.jl 中完成,以下是如何执行此操作的示例:

\n
julia> function helper2(x, i)\n           nonempty = false\n           local fv\n           for v in x\n               vv = v[i]\n               if !ismissing(vv)\n                   if nonempty\n                       vv == fv || return false\n                   else\n                       fv = vv\n                       nonempty = true\n                   end\n               end\n           end\n           return true\n       end\nhelper2 (generic function with 1 method)\n\njulia> df = DataFrame(mat, :auto, copycols=false); # copycols to avoid copying as data is large\n\njulia> @benchmark helper2.(Ref(identity.(eachcol($df))), 1:nrow($df))\nBenchmarkTools.Trial: 46 samples with 1 evaluation.\n Range (min \xe2\x80\xa6 max):  105.265 ms \xe2\x80\xa6 123.345 ms  \xe2\x94\x8a GC (min \xe2\x80\xa6 max): 0.00% \xe2\x80\xa6 0.00%\n Time  (median):     110.682 ms               \xe2\x94\x8a GC (median):    0.00%\n Time  (mean \xc2\xb1 \xcf\x83):   110.581 ms \xc2\xb1   2.692 ms  \xe2\x94\x8a GC (mean \xc2\xb1 \xcf\x83):  0.00% \xc2\xb1 0.00%\n\n                \xe2\x96\x84 \xe2\x96\x82 \xe2\x96\x84\xe2\x96\x88\xe2\x96\x82\n  \xe2\x96\x84\xe2\x96\x81\xe2\x96\x81\xe2\x96\x84\xe2\x96\x84\xe2\x96\x81\xe2\x96\x81\xe2\x96\x86\xe2\x96\x84\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x86\xe2\x96\x86\xe2\x96\x88\xe2\x96\x84\xe2\x96\x88\xe2\x96\x86\xe2\x96\x88\xe2\x96\x88\xe2\x96\x88\xe2\x96\x84\xe2\x96\x84\xe2\x96\x81\xe2\x96\x88\xe2\x96\x84\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x84\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x81\xe2\x96\x84 \xe2\x96\x81\n  105 ms           Histogram: frequency by time          123 ms <\n\n Memory estimate: 385.28 KiB, allocs estimate: 15.\n
Run Code Online (Sandbox Code Playgroud)\n

(如果代码中有任何不清楚的地方,请告诉我,我可以解释)

\n
\n

编辑

\n

如果你是一个独特的小联盟eltypes

\n
helper2.(Ref(collect(Union{unique(typeof.(eachcol(df)))...}, eachcol(df))), 1:nrow(df))\n
Run Code Online (Sandbox Code Playgroud)\n

如果Union{unique(typeof.(eachcol(df)))...}不是一个小集合,那么另一个解决方案会更好,所以请评论这是否对您来说足够好。

\n

  • 这表明您的源列“eltype”中存在显着的异质性。这是您原来的问题中不存在的内容。由于您要求“最有效”的代码,因此数据的确切特征非常重要 - 我针对您共享的数据优化了代码。我建议您使用您想要获得最有效代码的数据来更新您的问题。然后我就可以更新我的答案了。 (3认同)

هنر*_*تان 1

关于此的另一个更新,现在我能够使用 减少时间到一秒以下(实际上是 0.5 秒以下)InMemoryDatasets,这要归功于Julia lang 讨论中的讨论

julia> using InMemoryDatasets
julia> df = Dataset(df)
julia> f(x,y) = ismissing(x) || ismissing(y) ? true : x == y
julia> byrow(df, isless, [:v1, :v2, :v3], with = byrow(df, coalesce, :), lt = f)
Run Code Online (Sandbox Code Playgroud)

更新

通过讨论讨论的新更新,我几乎可以达到之前疯狂记录的一半:D,即 0.27(Julia 社区真的很喜欢 SPEED

julia> byrow(df, issorted, [:v1, :v2, :v3], lt = !f)
Run Code Online (Sandbox Code Playgroud)