191 lines
7.1 KiB
GDScript
191 lines
7.1 KiB
GDScript
@tool
|
|
extends Resource
|
|
class_name DataFrame
|
|
|
|
var table_name : String = ""
|
|
var labels : PackedStringArray = []
|
|
var headers : PackedStringArray = []
|
|
var datamatrix : Matrix = null
|
|
var dataset : Array = []
|
|
|
|
func _init(datamatrix : Matrix, headers : PackedStringArray = [], labels : PackedStringArray = [] , table_name : String = "") -> void:
|
|
if datamatrix.is_empty(): datamatrix.resize(labels.size(), headers.size())
|
|
if labels.is_empty() : for label in range(datamatrix.get_size().x) : labels.append(label as String)
|
|
if headers.is_empty() : for header in range(datamatrix.get_size().y) : headers.append(MatrixGenerator.get_letter_index(header))
|
|
build_dataframe(datamatrix, headers, labels, table_name)
|
|
|
|
func build_dataframe(datamatrix : Matrix, headers : PackedStringArray = [], labels : PackedStringArray = [] , table_name : String = "") -> void:
|
|
self.datamatrix = datamatrix
|
|
self.headers = headers
|
|
self.labels = labels
|
|
self.table_name = table_name
|
|
self.dataset = build_dataset_from_matrix(datamatrix, headers, labels)
|
|
|
|
func build_dataset_from_matrix(datamatrix : Matrix, headers : PackedStringArray, labels : PackedStringArray) -> Array:
|
|
var data : Array = datamatrix.to_array()
|
|
return build_dataset(data, headers, labels)
|
|
|
|
func build_dataset(data : Array, headers : PackedStringArray, labels : PackedStringArray) -> Array:
|
|
var dataset : Array = [Array([" "]) + Array(headers)]
|
|
for row_i in range(labels.size()): dataset.append(([labels[row_i]] + data[row_i]) if not data.is_empty() else [labels[row_i]])
|
|
return dataset
|
|
|
|
func insert_column(column : Array, header : String = "", index : int = dataset[0].size() - 1) -> void:
|
|
assert(column.size() == (datamatrix.rows() if not datamatrix.is_empty() else labels.size())) #,"error: the column size must match the dataset column size")
|
|
headers.insert(index, header if header != "" else MatrixGenerator.get_letter_index(index))
|
|
datamatrix.insert_column(column, index)
|
|
dataset = build_dataset_from_matrix(datamatrix, headers, labels)
|
|
|
|
func insert_row(row : Array, label : String = "", index : int = dataset.size() - 1) -> PackedStringArray:
|
|
assert(row.size() == (datamatrix.columns() if not datamatrix.is_empty() else headers.size())) #,"error: the row size must match the dataset row size")
|
|
labels.insert(index, label if label != "" else str(index))
|
|
datamatrix.insert_row(row, index)
|
|
dataset = build_dataset_from_matrix(datamatrix, headers, labels)
|
|
return PackedStringArray([label] + row)
|
|
|
|
func get_datamatrix() -> Matrix:
|
|
return datamatrix
|
|
|
|
func get_dataset() -> Array:
|
|
return dataset
|
|
|
|
func get_labels() -> PackedStringArray:
|
|
return labels
|
|
|
|
func transpose():
|
|
build_dataframe(MatrixGenerator.transpose(datamatrix), labels, headers, table_name)
|
|
|
|
func _to_string() -> String:
|
|
var last_string_len : int
|
|
for row in dataset:
|
|
for column in row:
|
|
var string_len : int = str(column).length()
|
|
last_string_len = string_len if string_len > last_string_len else last_string_len
|
|
var string : String = ""
|
|
for row_i in dataset.size():
|
|
for column_i in dataset[row_i].size():
|
|
string+="%*s" % [last_string_len+1, dataset[row_i][column_i]]
|
|
string+="\n"
|
|
string+="\n['{table_name}' : {rows} rows x {columns} columns]\n".format({
|
|
rows = datamatrix.rows(),
|
|
columns = datamatrix.columns(),
|
|
table_name = table_name})
|
|
return string
|
|
|
|
# ...............................................................................
|
|
|
|
# Return a list of headers corresponding to a list of indexes
|
|
func get_headers_names(indexes : PackedInt32Array) -> PackedStringArray:
|
|
var headers : PackedStringArray = []
|
|
for index in indexes:
|
|
headers.append(dataset[0][index])
|
|
return headers
|
|
|
|
# Returns the index of an header
|
|
func get_column_index(header : String) -> int:
|
|
for headers_ix in range(dataset[0].size()):
|
|
if dataset[0][headers_ix] == header:
|
|
return headers_ix
|
|
return -1
|
|
|
|
# Get a column by its header
|
|
func get_column(header : String) -> Array:
|
|
var headers_i : int = get_column_index(header)
|
|
if headers_i!=-1:
|
|
return datamatrix.get_column(headers_i)
|
|
else:
|
|
return []
|
|
|
|
# Get a list of columns by their headers
|
|
func columns(headers : PackedStringArray) -> Matrix:
|
|
var values : Array = []
|
|
for header in headers:
|
|
values.append(get_column(header))
|
|
return MatrixGenerator.transpose(Matrix.new(values))
|
|
|
|
|
|
# Get a column by its index
|
|
func get_icolumn(index : int) -> Array:
|
|
return datamatrix.get_column(index)
|
|
|
|
# Get a list of columns by their indexes
|
|
func get_icolumns(indexes : PackedInt32Array) -> Array:
|
|
var values : Array = []
|
|
for index in indexes:
|
|
values.append(datamatrix.get_column(index))
|
|
return values
|
|
|
|
# Returns the list of labels corresponding to the list of indexes
|
|
func get_labels_names(indexes : PackedInt32Array) -> PackedStringArray:
|
|
var headers : PackedStringArray = []
|
|
for index in indexes:
|
|
headers.append(dataset[index][0])
|
|
return headers
|
|
|
|
# Returns the index of a label
|
|
func get_row_index(label : String) -> int:
|
|
for row in dataset.size():
|
|
if dataset[row][0] == label:
|
|
return row
|
|
return -1
|
|
|
|
# Get a row by its label
|
|
func get_row(label : String) -> Array:
|
|
var index : int = get_row_index(label)
|
|
if index == -1 :
|
|
return []
|
|
else:
|
|
return datamatrix.get_row(index)
|
|
|
|
# Get a list of rows by their labels
|
|
func rows(labels : Array) -> Matrix:
|
|
var values : Array = []
|
|
for label in labels:
|
|
values.append(get_row(label))
|
|
return Matrix.new(values)
|
|
|
|
# Get a row by its index
|
|
func get_irow(index : int) -> Array:
|
|
return datamatrix.get_row(index)
|
|
|
|
# Get a list of rows by their indexes
|
|
func get_irows(indexes : PackedInt32Array) -> Array:
|
|
var values : Array = []
|
|
for index in indexes:
|
|
values.append(datamatrix.get_row(index))
|
|
return values
|
|
|
|
# Returns a a group of rows or a group of columns, using indexes or names
|
|
# dataset["0;5"] ---> Returns an array containing all rows from the 1st to the 4th
|
|
# dataset["0:5"] ---> Returns an array containing all columns from the 1st to the 4th
|
|
# dataset["label0;label5"] ---> Returns an array containing all row from the one with label == "label0" to the one with label == "label5"
|
|
# dataset["header0:header0"] ---> Returns an array containing all columns from the one with label == "label0" to the one with label == "label5"
|
|
func _get(_property : StringName):
|
|
# ":" --> Columns
|
|
if ":" in _property:
|
|
var property : PackedStringArray = _property.split(":")
|
|
if (property[0]).is_valid_int():
|
|
if property[1] == "*":
|
|
return get_icolumns(range(property[0] as int, headers.size()-1))
|
|
else:
|
|
return get_icolumns(range(property[0] as int, property[1] as int +1))
|
|
else:
|
|
if property[1] == "*":
|
|
return get_icolumns(range(get_column_index(property[0]), headers.size()-1))
|
|
else:
|
|
return get_icolumns(range(get_column_index(property[0]), get_column_index(property[1])))
|
|
# ";" --> Rows
|
|
elif ";" in _property:
|
|
var property : PackedStringArray = _property.split(";")
|
|
if (property[0]).is_valid_int():
|
|
return get_irows(range(property[0] as int, property[1] as int + 1 ))
|
|
else:
|
|
return get_irows(range(get_row_index(property[0]), get_row_index(property[1])))
|
|
elif "," in _property:
|
|
var property : PackedStringArray = _property.split(",")
|
|
else:
|
|
if (_property as String).is_valid_int():
|
|
return get_icolumn(int(_property))
|
|
else:
|
|
return get_column(_property)
|