Julia中没有值的DataFrame列?

Julia中没有值的DataFrame列?,julia,Julia,我正在努力理解Julia中的数据帧是如何工作的,我现在很不舒服 我通常使用Python中的DataFrames,在每个模拟步骤中添加新列,并用值填充每一行 例如,我有一个包含输入数据的数据框: using DataFrames df = DataFrame( A=Int[], B=Int[] ) push!(df, [1, 10]) push!(df, [2, 20]) push!(df, [3, 30]) 现在,让我们假设我基于那些A和B列进行计算,这些列生成第三列C,其中包含DateTi

我正在努力理解Julia中的数据帧是如何工作的,我现在很不舒服

我通常使用Python中的DataFrames,在每个模拟步骤中添加新列,并用值填充每一行

例如,我有一个包含输入数据的数据框:

using DataFrames

df = DataFrame( A=Int[], B=Int[] )
push!(df, [1, 10])
push!(df, [2, 20])
push!(df, [3, 30])
现在,让我们假设我基于那些
A
B
列进行计算,这些列生成第三列
C
,其中包含DateTime对象。但并非为所有行生成DateTime对象,它们可能为空

  • Julia如何处理该用例
  • 如何创建新的C列并在
    中为每个箭头(df)
    中的r赋值
  • 为了给出一个可运行的具体代码,让我们假设条件和函数:

    df[! :C] .= nothing
    
    for r in eachrow(df)
        if r.A == 2
            r.C = Dates.now()
        else
            r.C = nothing
        end
    end
    

    如果使用
    df[!,:C].=nothing初始化列,则该列具有元素类型
    nothing
    。将
    DateTime
    s写入此列时,Julia试图将其转换为
    Nothing
    ,但失败。 我不确定这是否是最有效或推荐的解决方案,但如果您将列初始化为
    DateTime
    Nothing

    df[!, :C] = Vector{Union{DateTime, Nothing}}(nothing, size(df, 1))
    

    您的示例应该有效。

    实现这一点的有效模式是:

    df.C = f.(df.A, df.B)
    
    其中,
    f
    是一个函数,它采用标量并基于标量计算输出(即模拟代码),然后将需要从
    df
    中提取的列传递给它以执行计算。通过这种方式,Julia编译器将能够生成快速(类型稳定)的本机代码

    在您的示例中,函数
    f
    将是
    ifelse
    ,因此您可以编写:

    df.C = ifelse.(df.A .== 2, Dates.now(), nothing)
    

    也可以考虑“<代码> > < <代码> >或代码>缺失< /代码>(它们在朱丽亚中有不同的解释:<代码>没有< /代码>表示值的缺失和<代码>缺少< /代码>意味着该值存在,但不知道;我不确定在您的情况下哪个更好)。我还注意到,我可以创建一个数组
    C=[]
    ,它的类型似乎是
    Any
    ,然后
    push
    元素。循环结束后,只需将
    C
    附加到数据帧
    df.C=C
    。不建议创建
    Any
    类型的向量(除非您确实必须这样做),因为以后使用它们会很慢(编译器不知道它们所持有的值的类型)。完美的答案!我会使用
    nrow(df)
    而不是
    size(df,1)
    ,这在我的笔记本电脑上要快20 ns;-)我将尝试这种方法。谢谢,这有助于更好地理解如何在Julia中工作。这是性能建议的一个特殊应用程序,它将与性能关键代码中的您相关。谢谢,我将查看链接以添加到Kaminski答案中。。在许多Julia操作中,使用
    nothing
    将导致运行时错误,而
    missing
    将导致
    missing
    以静默方式传播。如果选择缺少的情况,不要忘记将数据帧列定义为
    Union{t,missing}
    ,例如
    Union{Float64,missing}
    df.C = ifelse.(df.A .== 2, Dates.now(), nothing)