From 6334de0b75a93e74ca5ec7e0436514a58b2e3459 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Santilio?= Date: Mon, 21 Dec 2020 18:48:38 +0100 Subject: [PATCH] added DataFrame, Matrix, MatrixGenerator --- .../easy_charts/Utilities/Data/data_frame.gd | 85 +++++++++++++++++ addons/easy_charts/Utilities/Data/matrix.gd | 55 +++++++++++ .../Utilities/Data/matrix_generator.gd | 95 +++++++++++++++++++ 3 files changed, 235 insertions(+) create mode 100644 addons/easy_charts/Utilities/Data/data_frame.gd create mode 100644 addons/easy_charts/Utilities/Data/matrix.gd create mode 100644 addons/easy_charts/Utilities/Data/matrix_generator.gd diff --git a/addons/easy_charts/Utilities/Data/data_frame.gd b/addons/easy_charts/Utilities/Data/data_frame.gd new file mode 100644 index 0000000..8dbdc88 --- /dev/null +++ b/addons/easy_charts/Utilities/Data/data_frame.gd @@ -0,0 +1,85 @@ +tool +extends Reference +class_name DataFrame + +var _data_matrix : Matrix +var _index : PoolStringArray = [] +var _header : PoolStringArray = [] +var _dataframe : Array = [] +var _dataset : Array = [] + +func _init(data_matrix : Matrix, index : PoolStringArray, header : PoolStringArray) -> void: + if data_matrix.get_size()[1] == header.size(): header.insert(0,"") + if index.empty() : for value in range(data_matrix.get_size().x) : index.append("f%s"%value) + self._data_matrix = data_matrix + self._index = index + self._header = header + self._dataset = build_dataset(data_matrix.to_array(), index, header) + self._dataframe = build_dataframe_from_matrix(data_matrix, index, header) + +func build_dataset(data : Array, index : PoolStringArray, header : PoolStringArray) -> Array: + var dataset : Array = [Array(header)] + for i in range(index.size()): + var set : Array = data[i].duplicate() + set.insert(0, index[i]) + dataset.append(set) + return dataset + +func build_dataframe(data : Array, index : PoolStringArray, header : PoolStringArray) -> Array: + var dataframe : Array = [Array(header)] + for row_i in range(data.size()): dataframe.append([index[row_i]]+data[row_i]) + return dataframe + +func build_dataframe_from_matrix(data_matrix : Matrix, index : PoolStringArray, header : PoolStringArray) -> Array: + var data : Array = data_matrix.to_array() + return build_dataframe(data, index, header) + +func get_dataframe() -> Array: + return _dataframe + +func get_dataset() -> Array: + return _dataset + +func get_index() -> PoolStringArray: + return _index + +func _to_string() -> String: + var last_string_len : int + for row in _dataframe: + 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 = "\n" + for row_i in _dataframe.size(): + for column_i in _dataframe[row_i].size(): + string+="%*s" % [last_string_len+1, _dataframe[row_i][column_i]] + string+="\n" + return string + +# ............................................................................... +func get_column_h(header : String) -> Array: + var header_i : int = -1 + var array : Array = [] + for header_ix in range(_dataframe[0].size()): + if _dataframe[0][header_ix] == header: header_i = header_ix; continue + if header_i!=-1: for row in _dataframe: array.append(row[header_i]) + return array + +func get_row_i(index : String) -> Array: + var index_i : int + for row in _dataframe: if row[0] == index: return row + return [] + +func _get(_property : String): + if _property.split(";").size() == 2: + var property : PoolStringArray = _property.split(";") + pass + elif _property.split(":").size() == 2: + var property : PoolStringArray = _property.split(":") + if int(property[0]) == 0: return get_row_i(property[1]) + else: return get_column_h(property[1]) + + + + + diff --git a/addons/easy_charts/Utilities/Data/matrix.gd b/addons/easy_charts/Utilities/Data/matrix.gd new file mode 100644 index 0000000..718ecbc --- /dev/null +++ b/addons/easy_charts/Utilities/Data/matrix.gd @@ -0,0 +1,55 @@ +tool +extends Reference +class_name Matrix + +var _matrix : Array = [] + +func _init(matrix : Array = []) -> void: + _matrix = matrix + +func _to_string() -> String: + var last_string_len : int + for row in _matrix: + 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 = "\n" + for row_i in _matrix.size(): + for column_i in _matrix[row_i].size(): + string+="%*s" % [last_string_len+1 if column_i!=0 else last_string_len, _matrix[row_i][column_i]] + string+="\n" + return string + +func insert_row(row : Array, index : int = _matrix.size()) -> void: + _matrix.insert(index, row) + +func to_array() -> Array: + return _matrix.duplicate() + +func get_size() -> Vector2: + return Vector2(_matrix.size(), _matrix[0].size()) + +func get_column(column : int) -> Array: + if column >= get_size()[1]: printerr("error") + var column_array : Array = [] + for row in _matrix: column_array.append(row[column]) + return column_array + +func get_row(row : int) -> Array: + if row >= get_size()[0]: printerr("error") + return _matrix[row] +# +#func multiply_int(_int : int) -> void: +# _matrix = MatrixGenerator.multiply_int(self, _int).to_array() +# +#func multiply_float(_float : int) -> void: +# _matrix = MatrixGenerator.multiply_float(self, _float).to_array() + + + + + + + + + diff --git a/addons/easy_charts/Utilities/Data/matrix_generator.gd b/addons/easy_charts/Utilities/Data/matrix_generator.gd new file mode 100644 index 0000000..eac59df --- /dev/null +++ b/addons/easy_charts/Utilities/Data/matrix_generator.gd @@ -0,0 +1,95 @@ +tool +extends Reference +class_name MatrixGenerator + +# Generates a Matrix with random values between [from; to] with a given @size (rows, columns) +static func random_float_range(size : Vector2, from : float, to : float, _seed : int = 1234) -> Matrix: + seed(_seed) + randomize() + var array : Array = [] + for row in range(size.x): + var matrix_row : Array = [] + for column in range(size.y): matrix_row.append(rand_range(from,to)) + array.append(matrix_row) + return Matrix.new(array) + +# Generates a Matrix giving an Array (Array must by Array[Array]) +static func from_array(array : Array) -> Matrix: + var matrix : Array = [] + matrix.append(array) + return Matrix.new(matrix) + +# Generates a sub-Matrix giving a Matrix, a @from Array [row_i, column_i] and a @to Array [row_j, column_j] +static func sub_matrix(_matrix : Matrix, from : Array, to : Array) -> Matrix: + if to[0] > _matrix.get_size().x or to[1] > _matrix.get_size().y: + printerr("%s is not an acceptable size for the submatrix, giving a matrix of size %s"%[to, _matrix.get_size()]) + return Matrix.new() + var array : Array = [] + for rows_i in range(from[0],to[0]): array.append(_matrix.to_array()[rows_i].slice(from[1], to[1])) + return Matrix.new(array) + +# Duplicates a given Matrix +static func duplicate(_matrix : Matrix) -> Matrix: + return Matrix.new(_matrix.to_array().duplicate()) + +# Transpose a given Matrix +static func transpose(_matrix : Matrix) -> Matrix: + var array : Array = [] + array.resize(_matrix.get_size().y) + var row : Array = [] + row.resize(_matrix.get_size().x) + for x in array.size(): + array[x] = row.duplicate() + for i in range(_matrix.get_size().x): + for j in range(_matrix.get_size().y): + array[j][i] = (_matrix.to_array()[i][j]) + return Matrix.new(array) + +# Calculates the dot product (A*B) matrix between two Matrixes +static func dot(_matrix1 : Matrix, _matrix2 : Matrix) -> Matrix: + if _matrix1.get_size().y != _matrix2.get_size().x: + printerr("matrix1 number of columns: %s must be the same as matrix2 number of rows: %s"%[_matrix1.get_size().y, _matrix2.get_size().x]) + return Matrix.new() + var array : Array = [] + for x in range(_matrix1.get_size().x): + var row : Array = [] + for y in range(_matrix2.get_size().y): + var sum : float + for k in range(_matrix1.get_size().y): + sum += (_matrix1.to_array()[x][k]*_matrix2.to_array()[k][y]) + row.append(sum) + array.append(row) + return Matrix.new(array) + +# Calculates the hadamard (element-wise product) between two Matrixes +static func hadamard(_matrix1 : Matrix, _matrix2 : Matrix) -> Matrix: + if _matrix1.get_size() != _matrix2.get_size(): + printerr("matrix1 size: %s must be the same as matrix2 size: %s"%[_matrix1.get_size(), _matrix2.get_size()]) + return Matrix.new() + var array : Array = [] + for x in range(_matrix1.to_array().size()): + var row : Array = [] + for y in range(_matrix1.to_array()[x].size()): + row.append(_matrix1.to_array()[x][y] * _matrix2.to_array()[x][y]) + array.append(row) + return Matrix.new(array) + +# Multiply a given Matrix for an int value +static func multiply_int(_matrix1 : Matrix, _int : int) -> Matrix: + var array : Array = _matrix1.to_array().duplicate() + for x in range(_matrix1.to_array().size()): + for y in range(_matrix1.to_array()[x].size()): + array[x][y]*=_int + array[x][y] = int(array[x][y]) + return Matrix.new(array) + +# Multiply a given Matrix for a float value +static func multiply_float(_matrix1 : Matrix, _float : float) -> Matrix: + var array : Array = _matrix1.to_array().duplicate() + for x in range(_matrix1.to_array().size()): + for y in range(_matrix1.to_array()[x].size()): + array[x][y]*=_float + return Matrix.new(array) + + +