diff --git a/main.py b/main.py new file mode 100644 index 0000000..772c89d --- /dev/null +++ b/main.py @@ -0,0 +1,190 @@ +import pandas as pd +import sys +import numpy as np +import skfuzzy as fuzz +import matplotlib.pyplot as plt + +def fuzzy(goalsV, xGPerMatchV, shotsPerMatchV, onTargetPerMatchV): + goals = np.arange(0, 35, 1) + xGPerMatch = np.arange(0, 1, 0.01) + shotsPerMatch = np.arange(0, 5, 0.01) + onTargetPerMatch = np.arange(0, 5, 0.01) + ocena = np.arange(0, 101, 1) + + goals_low = fuzz.trapmf(goals, [0, 0, 10, 15]) + goals_md = fuzz.trimf(goals, [10, 15, 20]) + goals_hi = fuzz.trapmf(goals, [15, 20, 35, 100]) + xGPerMatch_lo = fuzz.trapmf(xGPerMatch, [0, 0, 0.2, 0.5]) + xGPerMatch_md = fuzz.trimf(xGPerMatch, [0.2, 0.5, 0.7]) + xGPerMatch_hi = fuzz.trapmf(xGPerMatch, [0.5, 0.7, 2, 10]) + shotsPerMatch_lo = fuzz.trapmf(shotsPerMatch, [0, 0, 1, 2]) + shotsPerMatch_md = fuzz.trapmf(shotsPerMatch, [1, 2, 3, 4]) + shotsPerMatch_hi = fuzz.trapmf(shotsPerMatch, [3, 4, 4.5, 10]) + onTargetPerMatch_lo = fuzz.trapmf(onTargetPerMatch, [0, 0, 0.5, 1]) + onTargetPerMatch_md = fuzz.trimf(onTargetPerMatch, [0.5, 1, 1.5]) + onTargetPerMatch_hi = fuzz.trimf(onTargetPerMatch, [1, 1.5, 5]) + ocena_lo = fuzz.trapmf(ocena, [0, 0, 40, 50]) + ocena_md = fuzz.trapmf(ocena, [40, 50, 60, 80]) + ocena_hi = fuzz.trapmf(ocena, [70, 80, 100, 100]) + + # + # fig, (ax0, ax1, ax2, ax3, ax4) = plt.subplots(nrows=5, figsize=(8, 9)) + # + # ax0.plot(goals, goals_low, 'b', linewidth=1.5, label='Mało') + # ax0.plot(goals, goals_md, 'g', linewidth=1.5, label='Średnio') + # ax0.plot(goals, goals_hi, 'r', linewidth=1.5, label='Dużo') + # ax0.set_title('Liczba bramek') + # ax0.legend() + # + # ax1.plot(xGPerMatch, xGPerMatch_lo, 'b', linewidth=1.5, label='Mało') + # ax1.plot(xGPerMatch, xGPerMatch_md, 'g', linewidth=1.5, label='Średno') + # ax1.plot(xGPerMatch, xGPerMatch_hi, 'r', linewidth=1.5, label='Dużo') + # ax1.set_title('Service quality') + # ax1.legend() + # + # ax2.plot(shotsPerMatch, shotsPerMatch_lo, 'b', linewidth=1.5, label='Mało') + # ax2.plot(shotsPerMatch, shotsPerMatch_md, 'g', linewidth=1.5, label='Średnio') + # ax2.plot(shotsPerMatch, shotsPerMatch_hi, 'r', linewidth=1.5, label='Dużo') + # ax2.set_title('Strzały na mecz') + # ax2.legend() + # + # ax3.plot(onTargetPerMatch, onTargetPerMatch_lo, 'b', linewidth=1.5, label='Mało') + # ax3.plot(onTargetPerMatch, onTargetPerMatch_md, 'g', linewidth=1.5, label='Średnio') + # ax3.plot(onTargetPerMatch, onTargetPerMatch_hi, 'r', linewidth=1.5, label='Dużo') + # ax3.set_title('Strzały w światlo bramki na mecz') + # ax3.legend() + # + # ax4.plot(ocena, ocena_lo, 'b', linewidth=1.5, label='Niska') + # ax4.plot(ocena, ocena_md, 'g', linewidth=1.5, label='Średnia') + # ax4.plot(ocena, ocena_hi, 'r', linewidth=1.5, label='Wysoka') + # ax4.set_title('Ocena') + # ax4.legend() + # + # # Turn off top/right axes + # for ax in (ax0, ax1, ax2, ax3, ax4): + # ax.spines['top'].set_visible(False) + # ax.spines['right'].set_visible(False) + # ax.get_xaxis().tick_bottom() + # ax.get_yaxis().tick_left() + # + # plt.tight_layout() + + goals_value = goalsV + xGPerMatch_value = xGPerMatchV + shotsPerMatch_value = shotsPerMatchV + onTargetPerMatch_value = onTargetPerMatchV + + goals_level_lo = fuzz.interp_membership(goals, goals_low, goals_value) + goals_level_md = fuzz.interp_membership(goals, goals_md, goals_value) + goals_level_hi = fuzz.interp_membership(goals, goals_hi, goals_value) + + xGPerMatch_level_lo = fuzz.interp_membership(xGPerMatch, xGPerMatch_lo, xGPerMatch_value) + xGPerMatch_level_md = fuzz.interp_membership(xGPerMatch, xGPerMatch_md, xGPerMatch_value) + xGPerMatch_level_hi = fuzz.interp_membership(xGPerMatch, xGPerMatch_hi, xGPerMatch_value) + + shotsPerMatch_level_lo = fuzz.interp_membership(shotsPerMatch, shotsPerMatch_lo, shotsPerMatch_value) + shotsPerMatch_level_md = fuzz.interp_membership(shotsPerMatch, shotsPerMatch_md, shotsPerMatch_value) + shotsPerMatch_level_hi = fuzz.interp_membership(shotsPerMatch, shotsPerMatch_hi, shotsPerMatch_value) + + onTargetPerMatch_level_lo = fuzz.interp_membership(onTargetPerMatch, onTargetPerMatch_lo, onTargetPerMatch_value) + onTargetPerMatch_level_md = fuzz.interp_membership(onTargetPerMatch, onTargetPerMatch_md, onTargetPerMatch_value) + onTargetPerMatch_level_hi = fuzz.interp_membership(onTargetPerMatch, onTargetPerMatch_hi, onTargetPerMatch_value) + + + active_rule1 = np.fmax(goals_level_hi, xGPerMatch_level_hi) + active_rule2 = np.fmax(active_rule1, onTargetPerMatch_level_hi) + + ocena_activation_hi = np.fmin(active_rule2, ocena_hi) # removed entirely to 0 + + active_rule3 = np.fmax(np.fmin(goals_level_lo, xGPerMatch_level_hi), + np.fmin(goals_level_lo, shotsPerMatch_level_hi)) + active_rule4=np.fmax(np.fmin(goals_level_md, xGPerMatch_level_md), np.fmin(goals_level_md, shotsPerMatch_level_md)) + active_rule5=np.fmax(active_rule3,active_rule4) + ocena_activation_md = np.fmin(active_rule5, ocena_md) + + ocena_activation_lo = np.fmin(goals_level_lo, ocena_lo) + ocena0 = np.zeros_like(ocena) + + # + # fig, ax0 = plt.subplots(figsize=(8, 3)) + # + # ax0.fill_between(ocena, ocena0, ocena_activation_lo, facecolor='b', alpha=0.7) + # ax0.plot(ocena, ocena_lo, 'b', linewidth=0.5, linestyle='--', ) + # ax0.fill_between(ocena, ocena0, ocena_activation_md, facecolor='g', alpha=0.7) + # ax0.plot(ocena, ocena_md, 'g', linewidth=0.5, linestyle='--') + # ax0.fill_between(ocena, ocena0, ocena_activation_hi, facecolor='r', alpha=0.7) + # ax0.plot(ocena, ocena_hi, 'r', linewidth=0.5, linestyle='--') + # ax0.set_title('Output membership activity') + # + # # Turn off top/right axes + # for ax in (ax0,): + # ax.spines['top'].set_visible(False) + # ax.spines['right'].set_visible(False) + # ax.get_xaxis().tick_bottom() + # ax.get_yaxis().tick_left() + # + # plt.tight_layout() + + aggregated = np.fmax(ocena_activation_lo, + np.fmax(ocena_activation_md, ocena_activation_hi)) + + # Calculate defuzzified result + ocena_output = fuzz.defuzz(ocena, aggregated, 'centroid') + ocena_activation = fuzz.interp_membership(ocena, aggregated, ocena_output) # for plot + + # # Visualize this + # fig, ax0 = plt.subplots(figsize=(8, 3)) + # + # ax0.plot(ocena, ocena_lo, 'b', linewidth=0.5, linestyle='--', ) + # ax0.plot(ocena, ocena_md, 'g', linewidth=0.5, linestyle='--') + # ax0.plot(ocena, ocena_hi, 'r', linewidth=0.5, linestyle='--') + # ax0.fill_between(ocena, ocena0, aggregated, facecolor='Orange', alpha=0.7) + # ax0.plot([ocena_output, ocena_output], [0, ocena_activation], 'k', linewidth=1.5, alpha=0.9) + # ax0.set_title('Aggregated membership and result (line)') + # + # # Turn off top/right axes + # for ax in (ax0,): + # ax.spines['top'].set_visible(False) + # ax.spines['right'].set_visible(False) + # ax.get_xaxis().tick_bottom() + # ax.get_yaxis().tick_left() + # + # plt.tight_layout() + + return ocena_output + + +def main(): + data = pd.read_csv("resources/Data.csv") + # league = sys.argv[1] + # year = sys.argv[2] + + # filtered_df = data.loc[data['Year'] == year] + filtered_df = data.loc[data['League'] == "La Liga"] + + #print(filtered_df) + + results = [] + + for item in filtered_df.iterrows(): + print(item) + goals=item[1]["Goals"] + xGPerMatch=item[1]["xG Per Avg Match"] + shotsPerMatch=item[1]["Shots Per Avg Match"] + onTargetPerMatch=item[1]["On Target Per Avg Match"] + rate = fuzzy(goals,xGPerMatch,shotsPerMatch,onTargetPerMatch) + results.append(rate) + + filtered_df['Rate'] = results + + filtered_df.to_csv('resources/out.csv') + + +if __name__ == '__main__': + main() + + +#goals srednio +#xG malo/srednio +#shotspM srednio +#onTarget malo/srednio \ No newline at end of file diff --git a/old.py b/old.py new file mode 100644 index 0000000..a6f050f --- /dev/null +++ b/old.py @@ -0,0 +1,161 @@ +import numpy as np +import skfuzzy as fuzz +import matplotlib.pyplot as plt + +# Generate universe variables +# * Quality and service on subjective ranges [0, 10] +# * Tip has a range of [0, 25] in units of percentage points +goals = np.arange(0, 35, 1) +xGPerMatch = np.arange(0, 1, 0.01) +shotsPerMatch=np.arange(0, 5, 0.01) +onTargetPerMatch = np.arange(0, 5, 0.01) +ocena=np.arange(0, 101, 1) + +# Generate fuzzy membership functions +goals_low = fuzz.trapmf(goals, [0, 0, 10,15]) +goals_md = fuzz.trimf(goals, [10, 15, 20]) +goals_hi = fuzz.trapmf(goals, [15, 20, 35, 100]) +xGPerMatch_lo = fuzz.trapmf(xGPerMatch, [0,0, 0.2, 0.5]) +xGPerMatch_md = fuzz.trimf(xGPerMatch, [0.2, 0.5, 0.7]) +xGPerMatch_hi = fuzz.trapmf(xGPerMatch, [0.5, 0.7, 2, 10]) +shotsPerMatch_lo = fuzz.trapmf(shotsPerMatch, [0,0, 1, 2]) +shotsPerMatch_md = fuzz.trapmf(shotsPerMatch, [1, 2, 3, 4]) +shotsPerMatch_hi = fuzz.trapmf(shotsPerMatch, [3, 4, 4.5, 10]) +onTargetPerMatch_lo = fuzz.trapmf(onTargetPerMatch, [0, 0, 0.5, 1]) +onTargetPerMatch_md = fuzz.trimf(onTargetPerMatch, [0.5, 1, 1.5]) +onTargetPerMatch_hi = fuzz.trimf(onTargetPerMatch, [1, 1.5, 5]) +ocena_lo = fuzz.trapmf(ocena, [0, 0, 40,50]) +ocena_md = fuzz.trapmf(ocena, [40, 50, 60, 80]) +ocena_hi = fuzz.trapmf(ocena, [70, 80, 100, 100]) + + +# Visualize these universes and membership functions +fig, (ax0, ax1, ax2, ax3, ax4) = plt.subplots(nrows=5, figsize=(8, 9)) + +ax0.plot(goals, goals_low, 'b', linewidth=1.5, label='Mało') +ax0.plot(goals, goals_md, 'g', linewidth=1.5, label='Średnio') +ax0.plot(goals, goals_hi, 'r', linewidth=1.5, label='Dużo') +ax0.set_title('Liczba bramek') +ax0.legend() + +ax1.plot(xGPerMatch, xGPerMatch_lo, 'b', linewidth=1.5, label='Mało') +ax1.plot(xGPerMatch, xGPerMatch_md, 'g', linewidth=1.5, label='Średno') +ax1.plot(xGPerMatch, xGPerMatch_hi, 'r', linewidth=1.5, label='Dużo') +ax1.set_title('Service quality') +ax1.legend() + +ax2.plot(shotsPerMatch, shotsPerMatch_lo, 'b', linewidth=1.5, label='Mało') +ax2.plot(shotsPerMatch, shotsPerMatch_md, 'g', linewidth=1.5, label='Średnio') +ax2.plot(shotsPerMatch, shotsPerMatch_hi, 'r', linewidth=1.5, label='Dużo') +ax2.set_title('Strzały na mecz') +ax2.legend() + +ax3.plot(onTargetPerMatch, onTargetPerMatch_lo, 'b', linewidth=1.5, label='Mało') +ax3.plot(onTargetPerMatch, onTargetPerMatch_md, 'g', linewidth=1.5, label='Średnio') +ax3.plot(onTargetPerMatch, onTargetPerMatch_hi, 'r', linewidth=1.5, label='Dużo') +ax3.set_title('Strzały w światlo bramki na mecz') +ax3.legend() + +ax4.plot(ocena, ocena_lo, 'b', linewidth=1.5, label='Niska') +ax4.plot(ocena, ocena_md, 'g', linewidth=1.5, label='Średnia') +ax4.plot(ocena, ocena_hi, 'r', linewidth=1.5, label='Wysoka') +ax4.set_title('Ocena') +ax4.legend() + +# Turn off top/right axes +for ax in (ax0, ax1, ax2, ax3, ax4): + ax.spines['top'].set_visible(False) + ax.spines['right'].set_visible(False) + ax.get_xaxis().tick_bottom() + ax.get_yaxis().tick_left() + +plt.tight_layout() +plt.show() + +goals_value=22 +xGPerMatch_value=0.9 +shotsPerMatch_value=4.43 +onTargetPerMatch_value=1.57 + +goals_level_lo = fuzz.interp_membership(goals, goals_low, goals_value) +goals_level_md = fuzz.interp_membership(goals, goals_md, goals_value) +goals_level_hi = fuzz.interp_membership(goals, goals_hi, goals_value) + +xGPerMatch_level_lo = fuzz.interp_membership(xGPerMatch, xGPerMatch_lo, xGPerMatch_value) +xGPerMatch_level_md = fuzz.interp_membership(xGPerMatch, xGPerMatch_md, xGPerMatch_value) +xGPerMatch_level_hi = fuzz.interp_membership(xGPerMatch, xGPerMatch_hi, xGPerMatch_value) + +shotsPerMatch_level_lo = fuzz.interp_membership(shotsPerMatch, shotsPerMatch_lo, shotsPerMatch_value) +shotsPerMatch_level_md = fuzz.interp_membership(shotsPerMatch, shotsPerMatch_md, shotsPerMatch_value) +shotsPerMatch_level_hi = fuzz.interp_membership(shotsPerMatch, shotsPerMatch_hi, shotsPerMatch_value) + +onTargetPerMatch_level_lo = fuzz.interp_membership(onTargetPerMatch, onTargetPerMatch_lo, onTargetPerMatch_value) +onTargetPerMatch_level_md = fuzz.interp_membership(onTargetPerMatch, onTargetPerMatch_md, onTargetPerMatch_value) +onTargetPerMatch_level_hi = fuzz.interp_membership(onTargetPerMatch, onTargetPerMatch_hi, onTargetPerMatch_value) + +# Now we take our rules and apply them. Rule 1 concerns bad food OR service. +# The OR operator means we take the maximum of these two. +active_rule1 = np.fmax(goals_level_hi, xGPerMatch_level_hi) +active_rule2=np.fmax(active_rule1, onTargetPerMatch_level_hi) + +# Now we apply this by clipping the top off the corresponding output +# membership function with `np.fmin` +ocena_activation_hi = np.fmin(active_rule2, ocena_hi) # removed entirely to 0 + +# For rule 2 we connect acceptable service to medium tipping +active_rule3=np.fmax(np.fmin(goals_level_lo,xGPerMatch_level_hi),np.fmin(goals_level_lo, shotsPerMatch_level_hi)) +ocena_activation_md = np.fmin(active_rule2, ocena_md) + +# For rule 3 we connect high service OR high food with high tipping +ocena_activation_lo = np.fmin(goals_level_lo, ocena_lo) +ocena0 = np.zeros_like(ocena) + +# Visualize this +fig, ax0 = plt.subplots(figsize=(8, 3)) + +ax0.fill_between(ocena, ocena0, ocena_activation_lo, facecolor='b', alpha=0.7) +ax0.plot(ocena, ocena_lo, 'b', linewidth=0.5, linestyle='--', ) +ax0.fill_between(ocena, ocena0, ocena_activation_md, facecolor='g', alpha=0.7) +ax0.plot(ocena, ocena_md, 'g', linewidth=0.5, linestyle='--') +ax0.fill_between(ocena, ocena0, ocena_activation_hi, facecolor='r', alpha=0.7) +ax0.plot(ocena, ocena_hi, 'r', linewidth=0.5, linestyle='--') +ax0.set_title('Output membership activity') + +# Turn off top/right axes +for ax in (ax0,): + ax.spines['top'].set_visible(False) + ax.spines['right'].set_visible(False) + ax.get_xaxis().tick_bottom() + ax.get_yaxis().tick_left() + +plt.tight_layout() +plt.show() + +aggregated = np.fmax(ocena_activation_lo, + np.fmax(ocena_activation_md, ocena_activation_hi)) + +# Calculate defuzzified result +ocena_output = fuzz.defuzz(ocena, aggregated, 'centroid') +ocena_activation = fuzz.interp_membership(ocena, aggregated, ocena_output) # for plot + +# Visualize this +fig, ax0 = plt.subplots(figsize=(8, 3)) + +ax0.plot(ocena, ocena_lo, 'b', linewidth=0.5, linestyle='--', ) +ax0.plot(ocena, ocena_md, 'g', linewidth=0.5, linestyle='--') +ax0.plot(ocena, ocena_hi, 'r', linewidth=0.5, linestyle='--') +ax0.fill_between(ocena, ocena0, aggregated, facecolor='Orange', alpha=0.7) +ax0.plot([ocena_output, ocena_output], [0, ocena_activation], 'k', linewidth=1.5, alpha=0.9) +ax0.set_title('Aggregated membership and result (line)') + +# Turn off top/right axes +for ax in (ax0,): + ax.spines['top'].set_visible(False) + ax.spines['right'].set_visible(False) + ax.get_xaxis().tick_bottom() + ax.get_yaxis().tick_left() + +plt.tight_layout() +plt.show() + +print(ocena_output) \ No newline at end of file