DataFrame: how to change value of a cell without knowing the row number

Is there any plan for functionality like pandas index and loc ?
Something like:

df = DataFrame(name=["John", "Sally", "Kirk"], age=[23., 42., 59.], children=[3,5,2])

setindex!( df,  :name  )


@chain df begin

    @transform      :Sally.age  = 30

    @rtransform     :Age_relative_to_Sally   =   :age  -  :Sally.age

end

Hi,
The solution proposed here does not seem to be compatible with last DataFrame version. What is the new syntax ? Thanks !

julia> using DataFrames, OhMyREPL

julia> df = DataFrame(name=["John", "Sally", "Kirk"], age=[23., 42., 59.], children=[3,5,2])
3Γ—3 DataFrame
 Row β”‚ name    age      children 
     β”‚ String  Float64  Int64    
─────┼───────────────────────────
   1 β”‚ John       23.0         3
   2 β”‚ Sally      42.0         5
   3 β”‚ Kirk       59.0         2

julia> df[(df[:name] .== "Sally"),:age]=99
ERROR: ArgumentError: syntax df[column] is not supported use df[!, column] instead
Stacktrace:
 [1] getindex(#unused#::DataFrame, #unused#::Symbol)
   @ DataFrames ~/.julia/packages/DataFrames/dgZn3/src/abstractdataframe/abstractdataframe.jl:2595
 [2] top-level scope
   @ REPL[3]:1

julia> df[(df[!,:name] .== "Sally"),:age]=99
ERROR: MethodError: no method matching setindex!(::DataFrame, ::Int64, ::BitVector, ::Symbol)
Closest candidates are:
  setindex!(::DataFrame, ::Any, ::Integer, ::Union{AbstractString, Signed, Symbol, Unsigned}) at ~/.julia/packages/DataFrames/dgZn3/src/dataframe/dataframe.jl:687
  setindex!(::DataFrame, ::AbstractVector, ::AbstractVector, ::Union{AbstractString, Signed, Symbol, Unsigned}) at ~/.julia/packages/DataFrames/dgZn3/src/dataframe/dataframe.jl:716
  setindex!(::AbstractDataFrame, ::Any, ::CartesianIndex{2}) at ~/.julia/packages/DataFrames/dgZn3/src/other/broadcasting.jl:5
  ...
Stacktrace:
 [1] top-level scope

Notice df[(df[:name] .== "Sally"),:age]=99 won’t work because df[:name] is not a syntax of DataFrames. You need to specify the rows, even if it’s all rows. So it should be df[:, :name] or df[!,:name]. If you want to avoid indicating β€œall rows”, just write df.name.

As for the second line you executed, df[(df.name.== "Sally"),:age] returns a vector. So you need to use Julia’s syntax to modify a vector. This means either:

  • df[(df.name.== "Sally"),:age] = [99]
  • df[(df.name.== "Sally"),:age] .= 99
1 Like

@alfaromartino thank you very much, your solution works fine :slight_smile:

julia> df[(df.name.== "Sally"),:age] = [99]
1-element Vector{Int64}:
 99

julia> df[(df.name.== "Sally"),:age] .= 99
1-element view(::Vector{Float64}, [2]) with eltype Float64:
 99.0