Как присвоить значение столбцу при переборе DataFrame, используя для каждой строки - PullRequest
3 голосов
/ 19 сентября 2019

У меня есть следующий код.Он в основном перебирает строки в кадре данных и пытается присвоить значение столбцу C.

Я попытался определить, как этого добиться, но безуспешно.Я знаю, что это предложение 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

Ответы [ 2 ]

2 голосов
/ 19 сентября 2019

Стандартный способ добавить столбец со значением часового в DataFrame:

df[!, :C] .= 0

insertcols! можно использовать, но обычно он используется, когда вы хотите вставить столбецв середине DataFrame (не как последний столбец, что делает мой пример).

Теперь цикл, который вы написали в конце вашего вопроса, можно записать как:

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)

(в общем - вы можете свободно использовать вещание при работе с фреймами данныхвместо петель)

2 голосов
/ 19 сентября 2019

Проблема в

insertcols! (Df, 3,: C => Int)

, где вы инициализируете столбец: C с типом (Int) вместо значения Int, как 0. Изменение этого параметра на

insertcols! (df, 3,: C => 0)

работает.

...