Spaces:
Runtime error
Runtime error
Download app.py from akhilhsingh/NPSAdjuster: direct link, hf CLI and curl.
- Browser
- Download file 5.64 kB
-
https://huggingface.co/spaces/akhilhsingh/NPSAdjuster/resolve/main/app.py
- Command line
-
hf download hf://spaces/akhilhsingh/NPSAdjuster/app.py
-
curl -L -o app.py https://huggingface.co/spaces/akhilhsingh/NPSAdjuster/resolve/main/app.py
5.64 kB
| import gradio as gr | |
| import pandas as pd | |
| import numpy as np | |
| import tempfile | |
| import os | |
| def calculate_nps(scores): | |
| scores = np.array(scores) | |
| total = len(scores) | |
| if total == 0: | |
| return 0 | |
| promoters = np.sum((scores == 4) | (scores == 5)) | |
| detractors = np.sum((scores == 1) | (scores == 2)) | |
| return (promoters - detractors) / total * 100 | |
| def adjust_nps(file, last_data_row, desired_nps_row, progress=gr.Progress(track_tqdm=False)): | |
| if file is None: | |
| raise gr.Error("Please upload an Excel file.") | |
| if last_data_row is None or desired_nps_row is None: | |
| raise gr.Error("Please enter both row numbers.") | |
| try: | |
| progress(0, desc="Reading file...") | |
| df = pd.read_excel(file.name, sheet_name="Data", header=None) | |
| except Exception as e: | |
| raise gr.Error(f"Could not read sheet named 'Data'. Error: {e}") | |
| # Convert user-friendly row numbers (e.g., 1503) to 0-based indices | |
| individual_score_start = 3 # as in your original script | |
| individual_score_end = int(last_data_row) - 1 | |
| desired_nps_row_idx = int(desired_nps_row) - 1 | |
| if individual_score_end <= individual_score_start: | |
| raise gr.Error("LAST data record row must be greater than 4 (since data starts at row 4).") | |
| last_column_index = df.shape[1] - 1 | |
| total_columns = last_column_index + 1 | |
| for col in range(0, last_column_index + 1): | |
| progress(col / total_columns, desc=f"Processing column {col + 1}/{total_columns}") | |
| # Get desired NPS for this column | |
| try: | |
| desired_nps = float(df.at[desired_nps_row_idx, col]) | |
| except (ValueError, TypeError): | |
| continue # skip if not a valid desired NPS | |
| except KeyError: | |
| continue | |
| original_scores = df.loc[individual_score_start:individual_score_end, col].copy() | |
| scores = pd.to_numeric(original_scores, errors="coerce").dropna() | |
| if len(scores) < 10: | |
| # Not enough data, skip column | |
| continue | |
| neutral_cap = np.random.uniform(3, 12) | |
| current_nps = calculate_nps(scores) | |
| changes = 0 | |
| max_changes = 400 | |
| while abs(current_nps - desired_nps) > 0.1 and changes < max_changes: | |
| neutral_percent = (scores == 3).sum() / len(scores) * 100 | |
| if current_nps > desired_nps: | |
| # Reduce NPS | |
| candidates = scores[(scores == 5) | (scores == 4)].index | |
| if len(candidates): | |
| idx = np.random.choice(candidates) | |
| scores.loc[idx] = 4 if scores.loc[idx] == 5 else 3 | |
| changes += 1 | |
| elif neutral_percent > 0: | |
| candidates = scores[scores == 3].index | |
| if len(candidates): | |
| idx = np.random.choice(candidates) | |
| scores.loc[idx] = 2 | |
| changes += 1 | |
| else: | |
| break | |
| else: | |
| break | |
| else: | |
| # Increase NPS | |
| if neutral_percent < neutral_cap: | |
| candidates = scores[scores == 2].index | |
| if len(candidates): | |
| idx = np.random.choice(candidates) | |
| scores.loc[idx] = 3 | |
| changes += 1 | |
| else: | |
| candidates = scores[scores == 3].index | |
| if len(candidates): | |
| idx = np.random.choice(candidates) | |
| scores.loc[idx] = 4 | |
| changes += 1 | |
| else: | |
| break | |
| else: | |
| candidates = scores[scores == 3].index | |
| if len(candidates): | |
| idx = np.random.choice(candidates) | |
| scores.loc[idx] = 4 | |
| changes += 1 | |
| else: | |
| break | |
| current_nps = calculate_nps(scores) | |
| # Write back adjusted scores | |
| df.loc[individual_score_start:individual_score_end, col] = scores | |
| progress(1, desc="Writing adjusted file...") | |
| # Save output to a temp file and return path | |
| temp_dir = tempfile.mkdtemp() | |
| output_path = os.path.join(temp_dir, "NeuroSinQ_NPS_Adjusted.xlsx") | |
| df.to_excel(output_path, index=False, header=False) | |
| return output_path | |
| with gr.Blocks(title="NeuroSinQ NPS Adjuster") as demo: | |
| gr.Markdown( | |
| """ | |
| # 🧠 NeuroSinQ NPS Adjuster | |
| 1. Upload an Excel file with **one worksheet** named **`Data`**. | |
| 2. Enter the **row number of LAST data record**. | |
| 3. Enter the **row number of Desired NPS**. | |
| 4. Click **Make Adjustment** to download the adjusted file. | |
| """ | |
| ) | |
| with gr.Row(): | |
| file_input = gr.File( | |
| label="Upload Excel File (.xlsx)", | |
| file_types=[".xlsx"], | |
| ) | |
| with gr.Row(): | |
| last_row = gr.Number( | |
| label="Row number of LAST data record (e.g., 1503)", | |
| precision=0 | |
| ) | |
| desired_row = gr.Number( | |
| label="Row number for Desired NPS (e.g., 1523)", | |
| precision=0 | |
| ) | |
| run_btn = gr.Button("⚙️ Make Adjustment") | |
| output_file = gr.File( | |
| label="Download Adjusted File", | |
| interactive=False | |
| ) | |
| run_btn.click( | |
| fn=adjust_nps, | |
| inputs=[file_input, last_row, desired_row], | |
| outputs=output_file | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch(ssr_mode=False) |