How to update data in a DataFrame

My project loads a CSV into a DataFrame and displays it in a Table (a MacOS app). So far so good ... but when trying to update a value in a column, I dont see anyway to update this value.

The table gets the value for the column like this:

 func getColumnValue(row :DataFrame.Rows.Element, columnName :String) -> String
 {
  if row.base.containsColumn(columnName)
  {
   var value = ""
   
   if row[columnName] != nil
   {
    value = "\(row[columnName]!)"
    }

   return value
   }
   ...

But the documentation and googles dont show any way to update the same column. Any help is appreciated with cookies.

Attempt to update:

 func setColumnValue(row :DataFrame.Rows.Element, columnName :String, value :String)
 {
  var column: [String?] = data[columnName]
  
  column[row.id] = value
 ...
  }
Answered by DTS Engineer in 816375022

I’m not 100% sure I understand your question, but if you just want to modify a value at a known column / row then you can do that using subscripts. Here’s a simple example that corrects the publication date of Planet of Exile:

import Foundation
import TabularData

let novels60s = """
    "Title","Year"
    "Rocannon's World","1966"
    "Planet of Exile","1967"
    "City of Illusions","1967"
    "A Wizard of Earthsea","1968"
    "The Left Hand of Darkness","1969"
    """

func test() throws {
    var df = try DataFrame(csvData: Data(novels60s.utf8))
    print("before:\n\(df)")
    df["Year"][1] = 1966
    print("after:\n\(df)")
}

try test()

It prints:

before:
┏━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━┓
┃   ┃ Title                     ┃ Year  ┃
┃   ┃ <String>                  ┃ <Int> ┃
┡━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━┩
│ 0 │ Rocannon's World          │ 1,966 │
│ 1 │ Planet of Exile           │ 1,967 │
│ 2 │ City of Illusions         │ 1,967 │
│ 3 │ A Wizard of Earthsea      │ 1,968 │
│ 4 │ The Left Hand of Darkness │ 1,969 │
└───┴───────────────────────────┴───────┘
5 rows, 2 columns

after:
┏━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━┓
┃   ┃ Title                     ┃ Year  ┃
┃   ┃ <String>                  ┃ <Int> ┃
┡━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━┩
│ 0 │ Rocannon's World          │ 1,966 │
│ 1 │ Planet of Exile           │ 1,966 │
│ 2 │ City of Illusions         │ 1,967 │
│ 3 │ A Wizard of Earthsea      │ 1,968 │
│ 4 │ The Left Hand of Darkness │ 1,969 │
└───┴───────────────────────────┴───────┘
5 rows, 2 columns

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I’m not 100% sure I understand your question, but if you just want to modify a value at a known column / row then you can do that using subscripts. Here’s a simple example that corrects the publication date of Planet of Exile:

import Foundation
import TabularData

let novels60s = """
    "Title","Year"
    "Rocannon's World","1966"
    "Planet of Exile","1967"
    "City of Illusions","1967"
    "A Wizard of Earthsea","1968"
    "The Left Hand of Darkness","1969"
    """

func test() throws {
    var df = try DataFrame(csvData: Data(novels60s.utf8))
    print("before:\n\(df)")
    df["Year"][1] = 1966
    print("after:\n\(df)")
}

try test()

It prints:

before:
┏━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━┓
┃   ┃ Title                     ┃ Year  ┃
┃   ┃ <String>                  ┃ <Int> ┃
┡━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━┩
│ 0 │ Rocannon's World          │ 1,966 │
│ 1 │ Planet of Exile           │ 1,967 │
│ 2 │ City of Illusions         │ 1,967 │
│ 3 │ A Wizard of Earthsea      │ 1,968 │
│ 4 │ The Left Hand of Darkness │ 1,969 │
└───┴───────────────────────────┴───────┘
5 rows, 2 columns

after:
┏━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━┓
┃   ┃ Title                     ┃ Year  ┃
┃   ┃ <String>                  ┃ <Int> ┃
┡━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━┩
│ 0 │ Rocannon's World          │ 1,966 │
│ 1 │ Planet of Exile           │ 1,966 │
│ 2 │ City of Illusions         │ 1,967 │
│ 3 │ A Wizard of Earthsea      │ 1,968 │
│ 4 │ The Left Hand of Darkness │ 1,969 │
└───┴───────────────────────────┴───────┘
5 rows, 2 columns

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thanks Eskimo for this ... I will apply the changes as you outlined !

Did not work .... the data table, is creating a dynamic field, based on the contents it is loading:

@ViewBuilder func createKeyField(row :DataFrame.Rows.Element, columnName :String) -> some View { let binding = Binding<String>( get: { dbModel.getColumnValue(row :row, columnName :columnName) }, set: { dbModel.setColumnValue(row :row, columnName :columnName, value :$0) } )

TextField("", text: binding) }

func setColumnValue(row :DataFrame.Rows.Element, columnName :String, value :String) { data[columnName][row.id] = value }

but the value does not get changed

How to update data in a DataFrame
 
 
Q