我试图了解DataFrames在Julia中的工作方式,我度过了艰难的时光。
我通常在Python中使用DataFrames-在每个模拟步骤中添加新列,并在每个行中填充值。
例如,我有一个包含输入数据的DataFrame:
using DataFrames
df = DataFrame( A=Int[], B=Int[] )
push!(df, [1, 10])
push!(df, [2, 20])
push!(df, [3, 30])
现在,假设我根据这些A
和B
列进行计算,这些列生成带有DateTime对象的第三列C
。但是并非所有行都生成DateTime对象,它们可以为null。
for r in eachrow(df)
内分配值?# Pseudocode of what I intend to do
df[! :C] .= nothing
for r in eachrow(df)
if condition
r.C = mySuperComplexFunctionThatReturnsDateTimeForEachRow()
else
r.C = nothing
end
end
要给出可运行且具体的代码,让我们伪造条件和函数:
df[! :C] .= nothing
for r in eachrow(df)
if r.A == 2
r.C = Dates.now()
else
r.C = nothing
end
end
答案 0 :(得分:3)
执行此操作的有效模式是:
df.C = f.(df.A, df.B)
其中f
是一个获取标量并基于标量计算输出的函数(即您的模拟代码),然后将需要从df
中提取的列传递给标量,以执行计算。这样,Julia编译器将能够生成快速的(类型稳定的)本地代码。
在您的示例中,函数f
将为ifelse
,因此您可以编写:
df.C = ifelse.(df.A .== 2, Dates.now(), nothing)
还要考虑是否返回nothing
或missing
(它们在Julia中的解释不同:nothing
表示不存在值,而missing
表示存在值但未知;我不确定哪种情况会更好。
答案 1 :(得分:2)
如果使用df[!, :C] .= nothing
初始化列,则其元素类型为Nothing
。将DateTime
写入此列时,Julia尝试将它们转换为Nothing
,但失败。
我不确定这是否是最有效或推荐的解决方案,但是如果您将该列初始化为DateTime
和Nothing
df[!, :C] = Vector{Union{DateTime, Nothing}}(nothing, size(df, 1))
您的示例应该可以使用。