def generateTree(training, gain, objectiveValues, attributes = None): usedAttributes = [] if attributes == None: remainingAttributes = copy(attributeNames) else: remainingAttributes = copy(attributes) root = Node(None) root.height = 0 F = deque([root]) E = [root] while len(F) > 0: curr = F.popleft() auxData = training for filter in curr.filters: auxData = auxData[ auxData[filter[0]] == filter[1]] gainsPerAttribute = {} if len(remainingAttributes) > 0: for aName in remainingAttributes: gainsPerAttribute[aName] = gain(training, [], obj, aName) currAttName = max(gainsPerAttribute, key=lambda key: gainsPerAttribute[key]) remainingAttributes = [att for att in remainingAttributes if att != currAttName] curr.value = currAttName attValues = list(data[currAttName].unique()) # print(auxData) for v in attValues: child = Node(curr) child.height = curr.height + 1 child.filters = copy(curr.filters) child.filters.append([currAttName, v]) childAuxData = auxData[auxData[currAttName] == v] # En este caso el subset para este nodo tiene ejemplos, # es decir, hay casos que cumplen con este filtro # más específico if len(childAuxData) != 0: ## Acá me fijo si todos los elementos del conjunto ## que me queda agregándole el filtro de este nodo ## son del mismo valor del objetivo -> el nodo es hoja leaf = False for ov in objectiveValues: if len(childAuxData[childAuxData[obj] == ov]) == len(childAuxData): leaf = True break if leaf: child.value = ov else: F.append(child) # En este caso, no hay nodos que cumplan con este nuevo filtro: # se crea una hoja cuyo valor es el más frecuente del atributo # objetivo en el conjunto del padre else: child.value = findMostFrequentObjectiveValue(auxData, obj, objectiveValues) curr.children[v] = child E.append(child) # Si no me quedan atributos, los nodos que quedan son hojas else: curr.value = findMostFrequentObjectiveValue(auxData, obj, objectiveValues) return root