Julia 如何使用for eachrow在数据帧上迭代时为列赋值
我有以下代码。它基本上迭代数据帧中的行,并尝试为列C赋值 我试图找到如何实现这一目标,但没有成功。我知道这个句子Julia 如何使用for eachrow在数据帧上迭代时为列赋值,julia,Julia,我有以下代码。它基本上迭代数据帧中的行,并尝试为列C赋值 我试图找到如何实现这一目标,但没有成功。我知道这个句子r.C=I*100是不正确的,哪一个是为每个迭代行的C列赋值的正确句子 请注意,这个问题是一个简化的示例,在我的实际代码中,我需要实际迭代每一行,因为计算要复杂得多 文件main2.jl: struct MyStruct a::Int32 b::Int32 c::String end df = DataFrame( A=Int[], B=Int[] ) pus
r.C=I*100
是不正确的,哪一个是为每个迭代行的C列赋值的正确句子
请注意,这个问题是一个简化的示例,在我的实际代码中,我需要实际迭代每一行,因为计算要复杂得多
文件main2.jl:
struct MyStruct
a::Int32
b::Int32
c::String
end
df = DataFrame( A=Int[], B=Int[] )
push!(df, [1, 10])
push!(df, [2, 20])
push!(df, [3, 30])
insertcols!(df, 3, :C => Int)
println(df)
i = 1
for r in eachrow(df)
global i
r.C = i*100
i = i + 1
end
我得到:
julia> include("main2.jl")
| A | B | C |
| Int64 | Int64 | DataType |
|-------|-------|----------|
| 1 | 10 | Int64 |
| 2 | 20 | Int64 |
| 3 | 30 | Int64 |
ERROR: LoadError: MethodError: Cannot `convert` an object of type Int64 to an object of type DataType
Closest candidates are:
convert(::Type{S}, ::T<:(Union{CategoricalString{R}, CategoricalValue{T,R} where T} where R)) where {S, T<:(Union{CategoricalString{R}, CategoricalValue{T,R} where T} where R)} at /home/.../.julia/packages/CategoricalArrays/qcwgl/src/value.jl:91
convert(::Type{T}, ::T) where T at essentials.jl:167
Stacktrace:
[1] setindex!(::Array{DataType,1}, ::Int64, ::Int64) at ./array.jl:766
[2] insert_single_entry!(::DataFrame, ::Int64, ::Int64, ::Int64) at /home/.../.julia/packages/DataFrames/yH0f6/src/dataframe/dataframe.jl:458
[3] setindex! at /home/.../.julia/packages/DataFrames/yH0f6/src/dataframe/dataframe.jl:497 [inlined]
[4] setindex! at /home/.../.julia/packages/DataFrames/yH0f6/src/dataframerow/dataframerow.jl:106 [inlined]
[5] setproperty!(::DataFrameRow{DataFrame,DataFrames.Index}, ::Symbol, ::Int64) at /home/.../.julia/packages/DataFrames/yH0f6/src/dataframerow/dataframerow.jl:129
[6] top-level scope at /usr/home/.../main2.jl:23
[7] include at ./boot.jl:328 [inlined]
[8] include_relative(::Module, ::String) at ./loading.jl:1094
[9] include(::Module, ::String) at ./Base.jl:31
[10] include(::String) at ./client.jl:431
[11] top-level scope at REPL[1]:1
in expression starting at /usr/home/.../main2.jl:21
julia>include(“main2.jl”)
|A | B | C|
|Int64 | Int64 |数据类型|
|-------|-------|----------|
|1 | 10 | Int64|
|2 | 20 | Int64|
|3 | 30 | Int64|
错误:LoadError:MethodError:无法将Int64类型的对象“转换”为DataType类型的对象
最接近的候选人是:
convert(::Type{S},::T问题出在
插入工具!(df,3,:C=>Int)
在这里,您使用类型(Int)而不是Int值(如0)初始化:C列
插入工具!(df,3,:C=>0)
有效。向数据帧添加具有sentinel值的列的标准方法是:
df[!, :C] .= 0
<代码> INSERTCOLS!可以使用,但通常在您要在“代码>数据文件中间插入一列时使用(不作为最后一列,我的示例是什么)。
现在,您在问题末尾所写的循环可以表述为:
for (i, r) in enumerate(eachrow(df))
r.C = i*100
end
我认为这是一种更典型的方法
最后,你可以简单地写下:
df.C = 100 .* axes(df, 1)
为了获得相同的效果。请注意,最后一条语句可能要复杂得多,如:
df.C = @. 100 * $axes(df, 1) + df.A + sin(df.B)
或者在这种情况下是等效的
df.C = 100 * axes(df, 1) + df.A + sin.(df.B)
(一般来说,当处理数据帧而不是循环时,您可以自由使用广播)如果我想插入一个包含给定结构的空数组的新列,该怎么办?我尝试:df[!,:C].=Vector{MyStruct}[]
但它不起作用,它说“LoadError:DiensionMismatch(”无法广播阵列以匹配目标“)
您的语句试图将一个MyStruct放入C列的每一行中。您可以创建一个包含3个MyStruct的列表,这将非常适合,因为您有3行。编译器可以重复类似于0的整数,但它不知道如何创建默认MyStruct,以便在收到MyStruct的空数组时填充列。我想要的是一个空的MyStruct每行中的y MyStruct数组,而不是每行中的一个MyStruct。或者一个“未定义”的数组,以后可以通过MyStruct.Harder数组通过为每个行中的r(df)
填充。创建一个伪结构,如m=MyStruct(0,0,”),然后df[!,:C]。=[m,m],[m]]应该可以。不过我想知道你是否不应该有更深层的数据帧结构。我认为一个标准的方法是df.C=Vector{MyStruct}(unde,nrow(df))
。这是明确的(代码在6个月后很容易阅读)和快速的(也就是说,您不需要在需要之前花费时间/内存来分配任何内容)。您还可以编写例如df[!,:C].=MyStruct.(df.A,df.B,“some_string”)
来一次性填充列(同样,在许多情况下,您可以使用广播而不是for循环)。谢谢,如果您想进一步说明正在添加的列是结构数组的情况,请参阅Bill回答中的注释(即,我打算在C列中添加可变长度的结构数组,我不知道是否可行)