Spaces:
Running
Running
James McCool
commited on
Commit
·
896d108
1
Parent(s):
a6e2b8d
Enhance player data handling in app.py by introducing a new data type selection feature. Users can now choose between "Team" and "Player" data types, allowing for more flexible data analysis. Updated the player data initialization function to support player-specific statistics, including average performance metrics based on game outcomes. This change improves the overall functionality and user experience of the application.
Browse files
app.py
CHANGED
@@ -27,6 +27,8 @@ def init_conn():
|
|
27 |
db, team_names, player_names, min_date, max_date = init_conn()
|
28 |
|
29 |
display_formats = {'wKill%': '{:.2%}', 'wDeath%': '{:.2%}', 'wAssist%': '{:.2%}', 'lKill%': '{:.2%}', 'lDeath%': '{:.2%}', 'lAssist%': '{:.2%}'}
|
|
|
|
|
30 |
|
31 |
# Create sidebar container for options
|
32 |
with st.sidebar:
|
@@ -59,13 +61,26 @@ with st.sidebar:
|
|
59 |
max_value=max_date.date()
|
60 |
)
|
61 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
62 |
col1, col2 = st.columns(2)
|
63 |
with col1:
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
69 |
with col2:
|
70 |
selected_opponent = st.selectbox(
|
71 |
"Select Opponent",
|
@@ -350,8 +365,213 @@ def init_team_data(team, opponent, win_loss_settings, kill_predictions, death_pr
|
|
350 |
|
351 |
return overall_team_data.dropna().set_index('playername'), opp_boosts, results_dict
|
352 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
353 |
if st.button("Run"):
|
354 |
-
|
|
|
|
|
|
|
355 |
|
356 |
player_summary = pd.DataFrame()
|
357 |
for game_num in range(game_count):
|
|
|
27 |
db, team_names, player_names, min_date, max_date = init_conn()
|
28 |
|
29 |
display_formats = {'wKill%': '{:.2%}', 'wDeath%': '{:.2%}', 'wAssist%': '{:.2%}', 'lKill%': '{:.2%}', 'lDeath%': '{:.2%}', 'lAssist%': '{:.2%}'}
|
30 |
+
leagues = ['AL', 'CBLOL', 'GLL', 'HM', 'LCK', 'LCS', 'LEC', 'LFL', 'LLA', 'LPL', 'LPLOL', 'LVP SL', 'MSI', 'PCS', 'PGN', 'PRM', 'TCL', 'VCS', 'LTAN', 'LTAS',
|
31 |
+
'LLA', 'LPL', 'LPLOL', 'LVP SL', 'MSI', 'PCS', 'PGN', 'PRM', 'TCL', 'VCS', 'LTAN', 'LTAS']
|
32 |
|
33 |
# Create sidebar container for options
|
34 |
with st.sidebar:
|
|
|
61 |
max_value=max_date.date()
|
62 |
)
|
63 |
|
64 |
+
# Date filtering options
|
65 |
+
st.subheader("Data Type")
|
66 |
+
data_type = st.radio(
|
67 |
+
"Select Data Type",
|
68 |
+
["Team", "Player"]
|
69 |
+
)
|
70 |
+
|
71 |
col1, col2 = st.columns(2)
|
72 |
with col1:
|
73 |
+
if data_type == "Player":
|
74 |
+
selected_players = st.multiselect(
|
75 |
+
"Select Players",
|
76 |
+
options=player_names
|
77 |
+
)
|
78 |
+
else:
|
79 |
+
selected_team = st.selectbox(
|
80 |
+
"Select Team",
|
81 |
+
options=team_names,
|
82 |
+
index=team_names.index("T1") if "T1" in team_names else 0
|
83 |
+
)
|
84 |
with col2:
|
85 |
selected_opponent = st.selectbox(
|
86 |
"Select Opponent",
|
|
|
365 |
|
366 |
return overall_team_data.dropna().set_index('playername'), opp_boosts, results_dict
|
367 |
|
368 |
+
@st.cache_data(ttl = 60)
|
369 |
+
def init_player_data(players, opponent, win_loss_settings, kill_predictions, death_predictions, start_date, end_date):
|
370 |
+
game_count = len(kill_predictions)
|
371 |
+
overall_team_data = pd.DataFrame(columns = ['playername', 'teamname', 'position', 'Kill_Proj', 'Death_Proj', 'Assist_Proj', 'CS_Proj'])
|
372 |
+
# Convert date objects to datetime strings in the correct format
|
373 |
+
start_datetime = datetime.combine(start_date, datetime.min.time()).strftime("%Y-%m-%d %H:%M:%S")
|
374 |
+
end_datetime = datetime.combine(end_date, datetime.max.time()).strftime("%Y-%m-%d %H:%M:%S")
|
375 |
+
|
376 |
+
collection = db["gamelogs"]
|
377 |
+
cursor = collection.find({"playername": players, "date": {"$gte": start_datetime, "$lte": end_datetime}})
|
378 |
+
raw_display = pd.DataFrame(list(cursor))
|
379 |
+
|
380 |
+
cursor = collection.find({"date": {"$gte": start_datetime, "$lte": end_datetime}})
|
381 |
+
raw_opponent = pd.DataFrame(list(cursor))
|
382 |
+
|
383 |
+
tables_to_loop = [raw_display, raw_opponent]
|
384 |
+
|
385 |
+
for loop in range(len(tables_to_loop)):
|
386 |
+
tables = tables_to_loop[loop]
|
387 |
+
calc_columns = ['kills', 'deaths', 'assists', 'total_cs']
|
388 |
+
league_pos_win_stats = {}
|
389 |
+
league_pos_loss_stats = {}
|
390 |
+
Opponent_pos_win_allowed_stats = {}
|
391 |
+
Opponent_pos_loss_allowed_stats = {}
|
392 |
+
playername_win_stats = {}
|
393 |
+
playername_loss_stats = {}
|
394 |
+
teamname_win_stats = {}
|
395 |
+
teamname_loss_stats = {}
|
396 |
+
|
397 |
+
if loop == 0:
|
398 |
+
|
399 |
+
for stats in calc_columns:
|
400 |
+
playername_win_stats[stats] = tables[tables['result'] == 1].groupby(['playername'])[stats].mean().to_dict()
|
401 |
+
playername_loss_stats[stats] = tables[tables['result'] == 0].groupby(['playername'])[stats].mean().to_dict()
|
402 |
+
teamname_win_stats[stats] = tables[(tables['result'] == 1) & (tables['position'] == 'team')].groupby(['teamname'])[stats].mean().to_dict()
|
403 |
+
teamname_loss_stats[stats] = tables[(tables['result'] == 0) & (tables['position'] == 'team')].groupby(['teamname'])[stats].mean().to_dict()
|
404 |
+
|
405 |
+
for stat in calc_columns:
|
406 |
+
|
407 |
+
column_name = f'playername_avg_{stat}_win'
|
408 |
+
tables[column_name] = tables.apply(
|
409 |
+
lambda row: playername_win_stats[stat].get(row['playername'], 0),
|
410 |
+
axis=1
|
411 |
+
)
|
412 |
+
|
413 |
+
column_name = f'playername_avg_{stat}_loss'
|
414 |
+
tables[column_name] = tables.apply(
|
415 |
+
lambda row: playername_loss_stats[stat].get(row['playername'], 0),
|
416 |
+
axis=1
|
417 |
+
)
|
418 |
+
|
419 |
+
column_name = f'teamname_avg_{stat}_win'
|
420 |
+
tables[column_name] = tables.apply(
|
421 |
+
lambda row: teamname_win_stats[stat].get(row['teamname'], 0),
|
422 |
+
axis=1
|
423 |
+
)
|
424 |
+
|
425 |
+
column_name = f'teamname_avg_{stat}_loss'
|
426 |
+
tables[column_name] = tables.apply(
|
427 |
+
lambda row: teamname_loss_stats[stat].get(row['teamname'], 0),
|
428 |
+
axis=1
|
429 |
+
)
|
430 |
+
|
431 |
+
tables['playername_avg_kill_share_win'] = tables['playername_avg_kills_win'] / tables['teamname_avg_kills_win']
|
432 |
+
tables['playername_avg_death_share_win'] = tables['playername_avg_deaths_win'] / tables['teamname_avg_deaths_win']
|
433 |
+
tables['playername_avg_assist_share_win'] = tables['playername_avg_assists_win'] / tables['teamname_avg_kills_win']
|
434 |
+
tables['playername_avg_cs_share_win'] = tables['playername_avg_total_cs_win'] / tables['teamname_avg_total_cs_win']
|
435 |
+
tables['playername_avg_kill_share_loss'] = tables['playername_avg_kills_loss'] / tables['teamname_avg_kills_loss']
|
436 |
+
tables['playername_avg_death_share_loss'] = tables['playername_avg_deaths_loss'] / tables['teamname_avg_deaths_loss']
|
437 |
+
tables['playername_avg_assist_share_loss'] = tables['playername_avg_assists_loss'] / tables['teamname_avg_kills_loss']
|
438 |
+
tables['playername_avg_cs_share_loss'] = tables['playername_avg_total_cs_loss'] / tables['teamname_avg_total_cs_loss']
|
439 |
+
player_tables = tables
|
440 |
+
|
441 |
+
else:
|
442 |
+
|
443 |
+
for stats in calc_columns:
|
444 |
+
league_pos_win_stats[stats] = {
|
445 |
+
league: group.groupby('position')[stats].mean().to_dict()
|
446 |
+
for league, group in tables[tables['result'] == 1].groupby('league')
|
447 |
+
}
|
448 |
+
league_pos_loss_stats[stats] = {
|
449 |
+
league: group.groupby('position')[stats].mean().to_dict()
|
450 |
+
for league, group in tables[tables['result'] == 0].groupby('league')
|
451 |
+
}
|
452 |
+
|
453 |
+
Opponent_pos_win_allowed_stats[stats] = {
|
454 |
+
opponent: group.groupby('position')[stats].mean().to_dict()
|
455 |
+
for opponent, group in tables[tables['result'] == 1].groupby('Opponent')
|
456 |
+
}
|
457 |
+
Opponent_pos_loss_allowed_stats[stats] = {
|
458 |
+
opponent: group.groupby('position')[stats].mean().to_dict()
|
459 |
+
for opponent, group in tables[tables['result'] == 0].groupby('Opponent')
|
460 |
+
}
|
461 |
+
|
462 |
+
for stat in calc_columns:
|
463 |
+
|
464 |
+
column_name = f'league_pos_avg_{stat}_win'
|
465 |
+
tables[column_name] = tables.apply(
|
466 |
+
lambda row: league_pos_win_stats[stat].get(row['league'], {}).get(row['position'], 0),
|
467 |
+
axis=1
|
468 |
+
)
|
469 |
+
|
470 |
+
column_name = f'league_pos_avg_{stat}_loss'
|
471 |
+
tables[column_name] = tables.apply(
|
472 |
+
lambda row: league_pos_loss_stats[stat].get(row['league'], {}).get(row['position'], 0),
|
473 |
+
axis=1
|
474 |
+
)
|
475 |
+
|
476 |
+
column_name = f'Opponent_pos_avg_{stat}_allowed_win'
|
477 |
+
tables[column_name] = tables.apply(
|
478 |
+
lambda row: Opponent_pos_win_allowed_stats[stat].get(row['Opponent'], {}).get(row['position'], 0),
|
479 |
+
axis=1
|
480 |
+
)
|
481 |
+
|
482 |
+
column_name = f'Opponent_pos_avg_{stat}_allowed_loss'
|
483 |
+
tables[column_name] = tables.apply(
|
484 |
+
lambda row: Opponent_pos_loss_allowed_stats[stat].get(row['Opponent'], {}).get(row['position'], 0),
|
485 |
+
axis=1
|
486 |
+
)
|
487 |
+
|
488 |
+
tables = tables[tables['Opponent'] == opponent]
|
489 |
+
|
490 |
+
tables['overall_win_kills_boost_pos'] = tables['Opponent_pos_avg_kills_allowed_win'] / tables['league_pos_avg_kills_win']
|
491 |
+
tables['overall_win_deaths_boost_pos'] = tables['Opponent_pos_avg_deaths_allowed_win'] / tables['league_pos_avg_deaths_win']
|
492 |
+
tables['overall_win_assists_boost_pos'] = tables['Opponent_pos_avg_assists_allowed_win'] / tables['league_pos_avg_assists_win']
|
493 |
+
tables['overall_win_total_cs_boost_pos'] = tables['Opponent_pos_avg_total_cs_allowed_win'] / tables['league_pos_avg_total_cs_win']
|
494 |
+
tables['overall_loss_kills_boost_pos'] = tables['Opponent_pos_avg_kills_allowed_loss'] / tables['league_pos_avg_kills_loss']
|
495 |
+
tables['overall_loss_deaths_boost_pos'] = tables['Opponent_pos_avg_deaths_allowed_loss'] / tables['league_pos_avg_deaths_loss']
|
496 |
+
tables['overall_loss_assists_boost_pos'] = tables['Opponent_pos_avg_assists_allowed_loss'] / tables['league_pos_avg_assists_loss']
|
497 |
+
tables['overall_loss_total_cs_boost_pos'] = tables['Opponent_pos_avg_total_cs_allowed_loss'] / tables['league_pos_avg_total_cs_loss']
|
498 |
+
|
499 |
+
opp_tables = tables
|
500 |
+
opp_pos_kills_boost_win = dict(zip(opp_tables['position'], opp_tables['overall_win_kills_boost_pos']))
|
501 |
+
opp_pos_deaths_boost_win = dict(zip(opp_tables['position'], opp_tables['overall_win_deaths_boost_pos']))
|
502 |
+
opp_pos_assists_boost_win = dict(zip(opp_tables['position'], opp_tables['overall_win_assists_boost_pos']))
|
503 |
+
opp_pos_cs_boost_win = dict(zip(opp_tables['position'], opp_tables['overall_win_total_cs_boost_pos']))
|
504 |
+
opp_pos_kills_boost_loss = dict(zip(opp_tables['position'], opp_tables['overall_loss_kills_boost_pos']))
|
505 |
+
opp_pos_deaths_boost_loss = dict(zip(opp_tables['position'], opp_tables['overall_loss_deaths_boost_pos']))
|
506 |
+
opp_pos_assists_boost_loss = dict(zip(opp_tables['position'], opp_tables['overall_loss_assists_boost_pos']))
|
507 |
+
opp_pos_cs_boost_loss = dict(zip(opp_tables['position'], opp_tables['overall_loss_total_cs_boost_pos']))
|
508 |
+
opp_boosts = pd.DataFrame({
|
509 |
+
'opp_pos_kills_boost_win': opp_pos_kills_boost_win,
|
510 |
+
'opp_pos_deaths_boost_win': opp_pos_deaths_boost_win,
|
511 |
+
'opp_pos_assists_boost_win': opp_pos_assists_boost_win,
|
512 |
+
'opp_pos_cs_boost_win': opp_pos_cs_boost_win,
|
513 |
+
'opp_pos_kills_boost_loss': opp_pos_kills_boost_loss,
|
514 |
+
'opp_pos_deaths_boost_loss': opp_pos_deaths_boost_loss,
|
515 |
+
'opp_pos_assists_boost_loss': opp_pos_assists_boost_loss,
|
516 |
+
'opp_pos_cs_boost_loss': opp_pos_cs_boost_loss
|
517 |
+
}).set_index(pd.Index(list(opp_pos_kills_boost_win.keys()), name='position'))
|
518 |
+
|
519 |
+
results_dict = {}
|
520 |
+
|
521 |
+
for game in range(game_count):
|
522 |
+
if kill_predictions[game] > 0:
|
523 |
+
working_tables = player_tables[['playername', 'teamname', 'position', 'playername_avg_kill_share_win', 'playername_avg_death_share_win','playername_avg_assist_share_win',
|
524 |
+
'playername_avg_total_cs_win', 'playername_avg_kill_share_loss', 'playername_avg_death_share_loss', 'playername_avg_assist_share_loss', 'playername_avg_total_cs_loss']]
|
525 |
+
working_tables = working_tables.rename(columns = {'playername_avg_kill_share_win': 'wKill%', 'playername_avg_death_share_win': 'wDeath%', 'playername_avg_assist_share_win': 'wAssist%',
|
526 |
+
'playername_avg_total_cs_win': 'wCS', 'playername_avg_kill_share_loss': 'lKill%', 'playername_avg_death_share_loss': 'lDeath%',
|
527 |
+
'playername_avg_assist_share_loss': 'lAssist%', 'playername_avg_total_cs_loss': 'lCS'})
|
528 |
+
team_data = working_tables.drop_duplicates(subset = ['playername'])
|
529 |
+
|
530 |
+
if win_loss_settings[game] == "Win":
|
531 |
+
team_data['Kill_Proj'] = team_data.apply(lambda row: row['wKill%'] * opp_pos_kills_boost_win.get(row['position'], 1), axis=1) * kill_predictions[game]
|
532 |
+
team_data['Death_Proj'] = team_data.apply(lambda row: row['wDeath%'] * opp_pos_deaths_boost_win.get(row['position'], 1), axis=1) * death_predictions[game]
|
533 |
+
team_data['Assist_Proj'] = team_data.apply(lambda row: row['wAssist%'] * opp_pos_assists_boost_win.get(row['position'], 1), axis=1) * kill_predictions[game]
|
534 |
+
team_data['CS_Proj'] = team_data.apply(lambda row: row['wCS'] * opp_pos_cs_boost_win.get(row['position'], 1), axis=1)
|
535 |
+
team_data = team_data[['playername', 'teamname', 'position', 'Kill_Proj', 'Death_Proj', 'Assist_Proj', 'CS_Proj']]
|
536 |
+
else:
|
537 |
+
team_data['Kill_Proj'] = team_data.apply(lambda row: row['lKill%'] * opp_pos_kills_boost_loss.get(row['position'], 1), axis=1) * kill_predictions[game]
|
538 |
+
team_data['Death_Proj'] = team_data.apply(lambda row: row['lDeath%'] * opp_pos_deaths_boost_loss.get(row['position'], 1), axis=1) * death_predictions[game]
|
539 |
+
team_data['Assist_Proj'] = team_data.apply(lambda row: row['lAssist%'] * opp_pos_assists_boost_loss.get(row['position'], 1), axis=1) * kill_predictions[game]
|
540 |
+
team_data['CS_Proj'] = team_data.apply(lambda row: row['lCS'] * opp_pos_cs_boost_loss.get(row['position'], 1), axis=1)
|
541 |
+
team_data = team_data[['playername', 'teamname', 'position', 'Kill_Proj', 'Death_Proj', 'Assist_Proj', 'CS_Proj']]
|
542 |
+
else:
|
543 |
+
working_tables = player_tables[['playername', 'teamname', 'position', 'playername_avg_kills_win', 'playername_avg_deaths_win', 'playername_avg_assists_win', 'playername_avg_total_cs_win',
|
544 |
+
'playername_avg_kills_loss', 'playername_avg_deaths_loss', 'playername_avg_assists_loss', 'playername_avg_total_cs_loss']]
|
545 |
+
working_tables = working_tables.rename(columns = {'playername_avg_kills_win': 'wKill%', 'playername_avg_deaths_win': 'wDeath%', 'playername_avg_assists_win': 'wAssist%',
|
546 |
+
'playername_avg_total_cs_win': 'wCS', 'playername_avg_kills_loss': 'lKill%', 'playername_avg_deaths_loss': 'lDeath%',
|
547 |
+
'playername_avg_assists_loss': 'lAssist%', 'playername_avg_total_cs_loss': 'lCS'})
|
548 |
+
team_data = working_tables.drop_duplicates(subset = ['playername'])
|
549 |
+
|
550 |
+
if win_loss_settings[game] == "Win":
|
551 |
+
team_data['Kill_Proj'] = team_data.apply(lambda row: row['wKill%'] * opp_pos_kills_boost_win.get(row['position'], 1), axis=1)
|
552 |
+
team_data['Death_Proj'] = team_data.apply(lambda row: row['wDeath%'] * opp_pos_deaths_boost_win.get(row['position'], 1), axis=1)
|
553 |
+
team_data['Assist_Proj'] = team_data.apply(lambda row: row['wAssist%'] * opp_pos_assists_boost_win.get(row['position'], 1), axis=1)
|
554 |
+
team_data['CS_Proj'] = team_data.apply(lambda row: row['wCS'] * opp_pos_cs_boost_win.get(row['position'], 1), axis=1)
|
555 |
+
team_data = team_data[['playername', 'teamname', 'position', 'Kill_Proj', 'Death_Proj', 'Assist_Proj', 'CS_Proj']]
|
556 |
+
else:
|
557 |
+
team_data['Kill_Proj'] = team_data.apply(lambda row: row['lKill%'] * opp_pos_kills_boost_loss.get(row['position'], 1), axis=1)
|
558 |
+
team_data['Death_Proj'] = team_data.apply(lambda row: row['lDeath%'] * opp_pos_deaths_boost_loss.get(row['position'], 1), axis=1)
|
559 |
+
team_data['Assist_Proj'] = team_data.apply(lambda row: row['lAssist%'] * opp_pos_assists_boost_loss.get(row['position'], 1), axis=1)
|
560 |
+
team_data['CS_Proj'] = team_data.apply(lambda row: row['lCS'] * opp_pos_cs_boost_loss.get(row['position'], 1), axis=1)
|
561 |
+
team_data = team_data[['playername', 'teamname', 'position', 'Kill_Proj', 'Death_Proj', 'Assist_Proj', 'CS_Proj']]
|
562 |
+
|
563 |
+
results_dict[f'game {game + 1}'] = team_data.dropna()
|
564 |
+
team_data['playername'] = team_data['playername'] + f' game {game + 1}'
|
565 |
+
|
566 |
+
overall_team_data = pd.concat([overall_team_data, team_data])
|
567 |
+
|
568 |
+
return overall_team_data.dropna().set_index('playername'), opp_boosts, results_dict
|
569 |
+
|
570 |
if st.button("Run"):
|
571 |
+
if data_type == "Team":
|
572 |
+
team_data, opp_boost, results_dict = init_team_data(selected_team, selected_opponent, win_loss_settings, kill_predictions, death_predictions, start_date, end_date)
|
573 |
+
else:
|
574 |
+
team_data, opp_boost, results_dict = init_player_data(selected_players, selected_opponent, win_loss_settings, kill_predictions, death_predictions, start_date, end_date)
|
575 |
|
576 |
player_summary = pd.DataFrame()
|
577 |
for game_num in range(game_count):
|