import pandas as pd from scipy.stats import chi2_contingency data = { 'Outlook': ['Sunny', 'Sunny', 'Overcast', 'Rain', 'Rain', 'Rain', 'Overcast', 'Sunny', 'Sunny', 'Rain', 'Sunny', 'Overcast', 'Overcast', 'Rain'], 'Temp.': ['Hot', 'Hot', 'Hot', 'Mild', 'Cool', 'Cool', 'Cool', 'Mild', 'Cold', 'Mild', 'Mild', 'Mild', 'Hot', 'Mild'], 'Humidity': ['High', 'High', 'High', 'High', 'Normal', 'Normal', 'Normal', 'High', 'Normal', 'Normal', 'Normal', 'High', 'Normal', 'High'], 'Wind': ['Weak', 'Strong', 'Weak', 'Weak', 'Weak', 'Strong', 'Strong', 'Weak', 'Weak', 'Weak', 'Strong', 'Strong', 'Weak', 'Strong'], 'Target': ['No', 'No', 'Yes', 'Yes', 'Yes', 'No', 'Yes', 'No', 'Yes', 'Yes', 'Yes', 'Yes', 'Yes', 'No'] } df = pd.DataFrame(data) def chaid_split(df, target_col, feature_col): contingency_table = pd.crosstab(df[feature_col], df[target_col]) chi2, p, dof, expected = chi2_contingency(contingency_table, correction=False) target_distribution = contingency_table.sum(axis=1) / contingency_table.sum().sum() return chi2, p, target_distribution.to_dict() node_counter = 0 # Initialize node counter def build_chaid_tree(df, target_col, features, forced_root_attributes, min_samples_split=5): global node_counter node_counter += 1 # Increment counter for each new node node_id = node_counter unique_targets = df[target_col].unique() if len(unique_targets) <= 1 or len(df) < min_samples_split: target_counts = df[target_col].value_counts() target_distribution = target_counts / target_counts.sum() return {'node_id': node_id, 'label': df[target_col].mode()[0], 'target_distribution': target_distribution.to_dict()} if forced_root_attributes: root_attribute = forced_root_attributes.pop(0) node = {'node_id': node_id, 'attribute': root_attribute, 'children': {}} for value in df[root_attribute].unique(): subset = df[df[root_attribute] == value] node['children'][value] = build_chaid_tree(subset, target_col, features, forced_root_attributes.copy(), min_samples_split) return node best_feature = None best_p_value = 1.0 best_chi2 = None best_target_distribution = None for feature in features: chi2, p, target_distribution = chaid_split(df, target_col, feature) if p < best_p_value: best_p_value = p best_feature = feature best_chi2 = chi2 best_target_distribution = target_distribution if best_feature is None: target_counts = df[target_col].value_counts() target_distribution = target_counts / target_counts.sum() return {'node_id': node_id, 'label': df[target_col].mode()[0], 'target_distribution': target_distribution.to_dict()} node = {'node_id': node_id, 'attribute': best_feature, 'chi2': best_chi2, 'p_value': best_p_value, 'target_distribution': best_target_distribution, 'children': {}} for value in df[best_feature].unique(): subset = df[df[best_feature] == value] child_node = build_chaid_tree(subset, target_col, features, [], min_samples_split) if 'chi2' not in child_node: child_node['chi2'] = None child_node['p_value'] = None child_node['target_distribution'] = child_node['target_distribution'] node['children'][value] = child_node return node def print_tree(tree, indent=""): print(f"Node {tree['node_id']}:") # Added node ID printing if 'label' in tree: print(f"{indent}Label: {tree['label']}") target_distribution = tree.get('target_distribution', {}) total_instances = sum(target_distribution.values()) for target, count in target_distribution.items(): percentage = (count / total_instances) * 100 if total_instances > 0 else 0 print(f"{indent} {target}: ({percentage:.2f}%)") else: print(f"{indent}Attribute: {tree['attribute']}") if 'chi2' in tree: print(f"{indent}Chi-Square: {tree['chi2']:.3f}") print(f"{indent}P-Value: {tree['p_value']:.3f}") target_distribution = tree.get('target_distribution', {}) total_instances = sum(target_distribution.values()) print(f"{indent}Target Distribution:") for target, count in target_distribution.items(): percentage = (count / total_instances) * 100 if total_instances > 0 else 0 print(f"{indent} {target}: ({percentage:.2f}%)") for value, child in tree['children'].items(): print_tree(child, indent + " ") tree = build_chaid_tree(df, 'Target', ['Outlook', 'Temp.', 'Humidity', 'Wind'], ['Outlook',"Wind","Humidity"], min_samples_split=3) print_tree(tree) Not tried anything yet Continue reading...