微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Julia DataFrame - 根据另一列中的值更新一列中的值的首选方法

如何解决Julia DataFrame - 根据另一列中的值更新一列中的值的首选方法

我正在尝试学习 Julia 中根据另一列中的值更新一列中的 DataFrame 的最佳方法。我主要使用 R,我可以在其中编写:

library(data.table)

dt <- data.table(A = 1:5,B = 6:10)
# A  B
# ----
# 1  6
# 2  7
# 3  8
# 4  9
# 5  10

dt[A < 3,B := B * 2]
# A  B
# ----
# 1  12
# 2  14
# 3  8
# 4  9
# 5  10

...它在 B 的位置更新 A < 3,而且非常简洁。我发现的唯一 Julia 等效项是:

using DataFrames

df = DataFrame(A = 1:5,B = 6:10)

transform!(df,[:A,:B] => ByRow((a,b) -> a < 3 ? b * 2 : a))

这是唯一的方法吗?它是首选吗?是否有任何软件包可以使这更简洁?

解决方法

目前您可以这样做:

@. df.B = ifelse(df.A < 3,2*df.B,df.B)

或者这个

df.B = @. ifelse(df.A < 3,df.B)

或者这个

dfv = view(df,df.A .< 3,:);
@. dfv.B = dfv.B * 2

第三种方法类似于 data.table 提供的方法,但您必须首先单独创建一个视图(data.table 在一个命令中执行的操作)。

第一种和第二种方法的区别在于 :B 列是就地更新还是替换。

,

虽然 Bogumił Kamiński 是这里的权威,his answer 展示了一个非常好的、简短的替代解决方案,但我相信还有更多讨论和示例的空间。

首先,您的原始解决方案肯定是惯用的,在很多情况下我个人更喜欢它。变异是高性能语言的重要工具,但它也是许多问题的根源。 Julia 约定(在某些其他语言中也很常见)在改变参数的函数中添加感叹号(或“砰!”),这在很大程度上有助于跟踪发生变异的位置。

就地赋值 (.=) 在 Julia 代码中也很常见,但在我自己的代码和许多库作者的代码中,这些通常会在按照约定命名的函数中找到,以便意图在通话现场很清楚。如果你发现你经常需要你描述的那种操作,你可以写一个函数:

function filter_transform!(df,pred,args...)
    fdf = filter(pred,df; view=true)
    fdf .= transform(copy(fdf),(col => f => col for (col,f) in args)...)
end

并使用它:

filter_transform!(df,:A => <(3),:B => b -> b*2)

我觉得读起来不错。该函数适用于您的原始示例,但不允许分配给另一列或在计算中使用多列或添加列(如 data.table 允许,NA 填充新列的跳过行)。这个稍微复杂的函数实现了:

applyif(cond,f,x,default) = cond ? f(x) : default
function filter_transform!(df,filt_cols,args...)
    colset = Set(keys(eachcol(df)))
    fcols,pred = filt_cols
    for (cols,(f,assign)) in args
        df[!,assign] .= in(assign,colset) ? df[!,assign] : missing
        @. df[!,assign] = applyif(pred(df[!,fcols]),df[!,cols],assign])
    end
end

使用:

filter_transform!(df,:B => (b -> b*2) => :B)

最后,您询问了软件包,确实有您可以查看的软件包:

Query.jl(此示例重新分配而不是就地修改):

using Query
df = df |> @mutate(B = _.A < 3 ? _.B*2 : _.B)

DataFramesMeta(也重新分配):

using DataFramesMeta
df = @eachrow df :B = :A < 3 ? :B*2 : :B

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。