Spaces:
Sleeping
Sleeping
Download pages/11_Collaborative_Features.py from Kedhareswer/DataVisl: direct link, hf CLI and curl.
- Browser
- Download file 29.4 kB
-
https://huggingface.co/spaces/Kedhareswer/DataVisl/resolve/main/pages/11_Collaborative_Features.py
- Command line
-
hf download hf://spaces/Kedhareswer/DataVisl/pages/11_Collaborative_Features.py
-
curl -L -o 11_Collaborative_Features.py https://huggingface.co/spaces/Kedhareswer/DataVisl/resolve/main/pages/11_Collaborative_Features.py
29.4 kB
| import streamlit as st | |
| import pandas as pd | |
| import numpy as np | |
| import json | |
| import base64 | |
| import io | |
| from datetime import datetime | |
| import os | |
| # Page configuration | |
| st.set_page_config( | |
| page_title="Collaborative Features", | |
| page_icon="👥", | |
| layout="wide" | |
| ) | |
| # Page title | |
| st.title("👥 Collaborative Features") | |
| st.markdown(""" | |
| Share your analysis, save projects for later, and collaborate with others | |
| by importing and exporting complete analysis workflows and results. | |
| """) | |
| # Create tabs for different collaborative features | |
| tab1, tab2, tab3 = st.tabs([ | |
| "Project Management", | |
| "Share Analysis", | |
| "Import/Export Workflows" | |
| ]) | |
| # Initialize project state if not exists | |
| if 'projects' not in st.session_state: | |
| st.session_state.projects = [] | |
| # Project Management Tab | |
| with tab1: | |
| st.subheader("Project Management") | |
| # Project saving section | |
| st.markdown(""" | |
| Save your current dataset and analysis settings as a project to continue working on it later. | |
| Projects are stored in your browser and will be available when you return. | |
| """) | |
| # Form for saving a project | |
| with st.form("save_project_form"): | |
| project_name = st.text_input("Project Name", placeholder="My Data Analysis Project") | |
| project_description = st.text_area("Description (optional)", placeholder="Brief description of this analysis project") | |
| col1, col2, col3 = st.columns([2, 1, 1]) | |
| with col1: | |
| project_tags = st.text_input("Tags (comma separated)", placeholder="finance, stocks, analysis") | |
| with col2: | |
| save_data = st.checkbox("Include Dataset", value=True) | |
| with col3: | |
| overwrite = st.checkbox("Overwrite if exists", value=False) | |
| save_button = st.form_submit_button("Save Project") | |
| if save_button: | |
| if not project_name: | |
| st.error("Please provide a project name.") | |
| else: | |
| try: | |
| # Check if project exists | |
| existing_project = False | |
| for i, project in enumerate(st.session_state.projects): | |
| if project['name'] == project_name: | |
| existing_project = True | |
| if overwrite: | |
| # Update existing project | |
| project_index = i | |
| break | |
| else: | |
| st.error(f"Project '{project_name}' already exists. Use 'Overwrite if exists' to replace it.") | |
| break | |
| # If project doesn't exist or we're overwriting | |
| if not existing_project or (existing_project and overwrite): | |
| # Create project data structure | |
| project_data = { | |
| 'name': project_name, | |
| 'description': project_description, | |
| 'tags': [tag.strip() for tag in project_tags.split(',')] if project_tags else [], | |
| 'date_created': datetime.now().strftime("%Y-%m-%d %H:%M:%S"), | |
| 'dataset_name': st.session_state.get('dataset_name', 'Unknown'), | |
| 'settings': {} | |
| } | |
| # Include dataset if selected | |
| if save_data and 'df' in st.session_state and st.session_state.df is not None: | |
| # Convert dataframe to CSV string | |
| csv_buffer = io.StringIO() | |
| st.session_state.df.to_csv(csv_buffer, index=False) | |
| csv_str = csv_buffer.getvalue() | |
| # Base64 encode to reduce storage size | |
| csv_bytes = csv_str.encode() | |
| b64_csv = base64.b64encode(csv_bytes).decode() | |
| # Add to project data | |
| project_data['dataset'] = b64_csv | |
| project_data['row_count'] = len(st.session_state.df) | |
| project_data['column_count'] = len(st.session_state.df.columns) | |
| else: | |
| project_data['dataset'] = None | |
| # Save the project | |
| if existing_project and overwrite: | |
| st.session_state.projects[project_index] = project_data | |
| st.success(f"Project '{project_name}' updated successfully!") | |
| else: | |
| st.session_state.projects.append(project_data) | |
| st.success(f"Project '{project_name}' saved successfully!") | |
| except Exception as e: | |
| st.error(f"Error saving project: {e}") | |
| # Project list section | |
| st.subheader("Your Saved Projects") | |
| if not st.session_state.projects: | |
| st.info("You don't have any saved projects yet.") | |
| else: | |
| # Filter and search options | |
| col1, col2 = st.columns([3, 1]) | |
| with col1: | |
| search_term = st.text_input("Search Projects", placeholder="Enter project name or tag") | |
| with col2: | |
| sort_by = st.selectbox("Sort By", ["Date (newest)", "Date (oldest)", "Name (A-Z)", "Name (Z-A)"]) | |
| # Filter projects based on search term | |
| filtered_projects = st.session_state.projects | |
| if search_term: | |
| filtered_projects = [ | |
| p for p in filtered_projects if ( | |
| search_term.lower() in p['name'].lower() or | |
| search_term.lower() in p['description'].lower() or | |
| any(search_term.lower() in tag.lower() for tag in p['tags']) | |
| ) | |
| ] | |
| # Sort projects | |
| if sort_by == "Date (newest)": | |
| filtered_projects = sorted(filtered_projects, key=lambda p: p['date_created'], reverse=True) | |
| elif sort_by == "Date (oldest)": | |
| filtered_projects = sorted(filtered_projects, key=lambda p: p['date_created']) | |
| elif sort_by == "Name (A-Z)": | |
| filtered_projects = sorted(filtered_projects, key=lambda p: p['name']) | |
| elif sort_by == "Name (Z-A)": | |
| filtered_projects = sorted(filtered_projects, key=lambda p: p['name'], reverse=True) | |
| # Display projects in a grid | |
| if filtered_projects: | |
| # Create 3 columns for the grid | |
| cols = st.columns(3) | |
| # Display each project in the grid | |
| for i, project in enumerate(filtered_projects): | |
| col_index = i % 3 | |
| with cols[col_index]: | |
| st.markdown(f""" | |
| <div style=" | |
| border: 1px solid #ddd; | |
| border-radius: 5px; | |
| padding: 10px; | |
| margin-bottom: 15px; | |
| "> | |
| <h4>{project['name']}</h4> | |
| <p><small>{project['date_created']}</small></p> | |
| <p>{project['description']}</p> | |
| <p> | |
| <small> | |
| {'Dataset: ' + (str(project.get('row_count', 'N/A')) + ' rows × ' + str(project.get('column_count', 'N/A')) + ' columns' if project.get('dataset') else 'No dataset')} | |
| </small> | |
| </p> | |
| <p> | |
| <small> | |
| {', '.join(['#' + tag for tag in project['tags']]) if project['tags'] else 'No tags'} | |
| </small> | |
| </p> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| c1, c2, c3 = st.columns([1, 1, 1]) | |
| with c1: | |
| if st.button("Load", key=f"load_{i}"): | |
| # Load the project | |
| if project.get('dataset'): | |
| try: | |
| # Decode base64 to CSV | |
| b64_csv = project['dataset'] | |
| csv_bytes = base64.b64decode(b64_csv) | |
| csv_str = csv_bytes.decode() | |
| # Load CSV into dataframe | |
| csv_buffer = io.StringIO(csv_str) | |
| loaded_df = pd.read_csv(csv_buffer) | |
| # Update session state | |
| st.session_state.df = loaded_df | |
| st.session_state.dataset_name = project['name'] | |
| st.success(f"Project '{project['name']}' loaded successfully!") | |
| st.rerun() | |
| except Exception as e: | |
| st.error(f"Error loading project data: {e}") | |
| else: | |
| st.warning("This project does not include dataset. Only project metadata was loaded.") | |
| with c2: | |
| if st.button("Delete", key=f"delete_{i}"): | |
| # Ask for confirmation | |
| st.session_state.delete_index = i | |
| st.info(f"Are you sure you want to delete project '{project['name']}'?") | |
| st.button("Yes, Delete", key=f"confirm_delete_{i}", on_click=lambda: delete_project(i)) | |
| with c3: | |
| if st.button("Export", key=f"export_{i}"): | |
| # Export the project to JSON | |
| try: | |
| project_json = json.dumps(project, indent=2) | |
| b64 = base64.b64encode(project_json.encode()).decode() | |
| href = f'<a href="data:application/json;base64,{b64}" download="{project["name"].replace(" ", "_")}.json">Download Project JSON</a>' | |
| st.markdown(href, unsafe_allow_html=True) | |
| except Exception as e: | |
| st.error(f"Error exporting project: {e}") | |
| else: | |
| st.info("No projects match your search criteria.") | |
| # Function to delete a project | |
| def delete_project(index): | |
| if 0 <= index < len(st.session_state.projects): | |
| project_name = st.session_state.projects[index]['name'] | |
| del st.session_state.projects[index] | |
| st.success(f"Project '{project_name}' deleted successfully!") | |
| st.rerun() | |
| # Share Analysis Tab | |
| with tab2: | |
| st.subheader("Share Your Analysis") | |
| # Analysis report generation | |
| st.markdown(""" | |
| Generate a sharable report of your current analysis, including visualizations and insights. | |
| You can download the report in various formats or get a shareable link. | |
| """) | |
| # Check if data is loaded | |
| if 'df' not in st.session_state or st.session_state.df is None: | |
| st.warning("Please load a dataset first to generate a report.") | |
| else: | |
| # Report options | |
| st.subheader("Report Configuration") | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| report_title = st.text_input("Report Title", value=f"Analysis of {st.session_state.dataset_name}") | |
| report_author = st.text_input("Author/Organization") | |
| with col2: | |
| include_options = st.multiselect( | |
| "Include in Report", | |
| ["Dataset Info", "Data Preview", "Summary Statistics", "Visualizations", "Insights"], | |
| default=["Dataset Info", "Data Preview", "Summary Statistics"] | |
| ) | |
| report_format = st.selectbox( | |
| "Report Format", | |
| ["HTML", "PDF", "JSON"] | |
| ) | |
| if st.button("Generate Report"): | |
| with st.spinner("Generating report..."): | |
| try: | |
| # Create basic report data | |
| report_data = { | |
| "title": report_title, | |
| "author": report_author, | |
| "date": datetime.now().strftime("%Y-%m-%d %H:%M:%S"), | |
| "dataset_name": st.session_state.dataset_name, | |
| "sections": [] | |
| } | |
| # Include selected sections | |
| if "Dataset Info" in include_options: | |
| dataset_info = { | |
| "section_title": "Dataset Information", | |
| "content": { | |
| "rows": len(st.session_state.df), | |
| "columns": len(st.session_state.df.columns), | |
| "column_names": st.session_state.df.columns.tolist(), | |
| "data_types": {col: str(dtype) for col, dtype in st.session_state.df.dtypes.items()} | |
| } | |
| } | |
| report_data["sections"].append(dataset_info) | |
| if "Data Preview" in include_options: | |
| data_preview = { | |
| "section_title": "Data Preview", | |
| "content": { | |
| "preview": st.session_state.df.head(10).to_dict(orient="records") | |
| } | |
| } | |
| report_data["sections"].append(data_preview) | |
| if "Summary Statistics" in include_options: | |
| # Get numeric columns for summary stats | |
| numeric_cols = st.session_state.df.select_dtypes(include=['number']).columns.tolist() | |
| if numeric_cols: | |
| summary_stats = { | |
| "section_title": "Summary Statistics", | |
| "content": { | |
| "stats": st.session_state.df[numeric_cols].describe().to_dict() | |
| } | |
| } | |
| report_data["sections"].append(summary_stats) | |
| # Generate report based on format | |
| if report_format == "JSON": | |
| # Convert report data to JSON | |
| report_json = json.dumps(report_data, indent=2) | |
| # Create download link | |
| b64 = base64.b64encode(report_json.encode()).decode() | |
| filename = f"{report_title.replace(' ', '_')}_report.json" | |
| href = f'<a href="data:application/json;base64,{b64}" download="{filename}">Download Report JSON</a>' | |
| st.success("Report generated successfully!") | |
| st.markdown(href, unsafe_allow_html=True) | |
| elif report_format == "HTML": | |
| # Create a simple HTML report | |
| html_report = f""" | |
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <title>{report_title}</title> | |
| <style> | |
| body {{ font-family: Arial, sans-serif; margin: 20px; line-height: 1.6; }} | |
| h1 {{ color: #1E88E5; }} | |
| h2 {{ color: #0D47A1; margin-top: 20px; }} | |
| .metadata {{ color: #666; font-style: italic; margin-bottom: 20px; }} | |
| table {{ border-collapse: collapse; width: 100%; }} | |
| th, td {{ border: 1px solid #ddd; padding: 8px; text-align: left; }} | |
| th {{ background-color: #f2f2f2; }} | |
| tr:hover {{ background-color: #f5f5f5; }} | |
| </style> | |
| </head> | |
| <body> | |
| <h1>{report_title}</h1> | |
| <div class="metadata"> | |
| <p>Author: {report_author if report_author else 'Anonymous'}</p> | |
| <p>Date: {report_data['date']}</p> | |
| <p>Dataset: {report_data['dataset_name']}</p> | |
| </div> | |
| """ | |
| # Add sections | |
| for section in report_data["sections"]: | |
| section_title = section["section_title"] | |
| content = section["content"] | |
| html_report += f"<h2>{section_title}</h2>" | |
| if section_title == "Dataset Information": | |
| html_report += f""" | |
| <p>Rows: {content['rows']}</p> | |
| <p>Columns: {content['columns']}</p> | |
| <h3>Columns:</h3> | |
| <table> | |
| <tr> | |
| <th>Column Name</th> | |
| <th>Data Type</th> | |
| </tr> | |
| """ | |
| for col in content['column_names']: | |
| html_report += f""" | |
| <tr> | |
| <td>{col}</td> | |
| <td>{content['data_types'][col]}</td> | |
| </tr> | |
| """ | |
| html_report += "</table>" | |
| elif section_title == "Data Preview": | |
| preview = content['preview'] | |
| if preview: | |
| # Create table headers | |
| html_report += """ | |
| <table> | |
| <tr> | |
| """ | |
| for col in preview[0].keys(): | |
| html_report += f"<th>{col}</th>" | |
| html_report += "</tr>" | |
| # Add data rows | |
| for row in preview: | |
| html_report += "<tr>" | |
| for col, val in row.items(): | |
| html_report += f"<td>{val}</td>" | |
| html_report += "</tr>" | |
| html_report += "</table>" | |
| elif section_title == "Summary Statistics": | |
| stats = content['stats'] | |
| if stats: | |
| # Create table headers | |
| html_report += """ | |
| <table> | |
| <tr> | |
| <th>Statistic</th> | |
| """ | |
| for col in stats.keys(): | |
| html_report += f"<th>{col}</th>" | |
| html_report += "</tr>" | |
| # Add stats rows | |
| for stat in ['count', 'mean', 'std', 'min', '25%', '50%', '75%', 'max']: | |
| html_report += f"<tr><td>{stat}</td>" | |
| for col, values in stats.items(): | |
| value = values.get(stat, "") | |
| if isinstance(value, (int, float)): | |
| value = f"{value:.4f}" if stat != 'count' else f"{int(value)}" | |
| html_report += f"<td>{value}</td>" | |
| html_report += "</tr>" | |
| html_report += "</table>" | |
| # Close HTML | |
| html_report += """ | |
| </body> | |
| </html> | |
| """ | |
| # Create download link | |
| b64 = base64.b64encode(html_report.encode()).decode() | |
| filename = f"{report_title.replace(' ', '_')}_report.html" | |
| href = f'<a href="data:text/html;base64,{b64}" download="{filename}">Download HTML Report</a>' | |
| st.success("Report generated successfully!") | |
| st.markdown(href, unsafe_allow_html=True) | |
| # Preview | |
| with st.expander("Preview HTML Report", expanded=False): | |
| st.components.v1.html(html_report, height=500, scrolling=True) | |
| elif report_format == "PDF": | |
| st.info("PDF export requires additional libraries. Please use HTML or JSON format instead.") | |
| except Exception as e: | |
| st.error(f"Error generating report: {e}") | |
| # Import/Export Workflows Tab | |
| with tab3: | |
| st.subheader("Import and Export Workflows") | |
| st.markdown(""" | |
| Save your entire analysis workflow, including dataset, transformations, and visualizations. | |
| Export workflows to share with others or import workflows created by your colleagues. | |
| """) | |
| # Export workflow section | |
| st.subheader("Export Current Workflow") | |
| # Check if data is loaded | |
| if 'df' not in st.session_state or st.session_state.df is None: | |
| st.warning("Please load a dataset first to export a workflow.") | |
| else: | |
| # Workflow export options | |
| include_data = st.checkbox("Include Dataset", value=True) | |
| if st.button("Export Workflow"): | |
| with st.spinner("Preparing workflow export..."): | |
| try: | |
| # Create workflow data structure | |
| workflow_data = { | |
| 'name': st.session_state.get('dataset_name', 'Unnamed Workflow'), | |
| 'date_exported': datetime.now().strftime("%Y-%m-%d %H:%M:%S"), | |
| 'settings': {} | |
| } | |
| # Include dataset if selected | |
| if include_data: | |
| # Convert dataframe to CSV string | |
| csv_buffer = io.StringIO() | |
| st.session_state.df.to_csv(csv_buffer, index=False) | |
| csv_str = csv_buffer.getvalue() | |
| # Base64 encode to reduce storage size | |
| csv_bytes = csv_str.encode() | |
| b64_csv = base64.b64encode(csv_bytes).decode() | |
| # Add to workflow data | |
| workflow_data['dataset'] = b64_csv | |
| workflow_data['row_count'] = len(st.session_state.df) | |
| workflow_data['column_count'] = len(st.session_state.df.columns) | |
| else: | |
| workflow_data['dataset'] = None | |
| # Convert workflow to JSON | |
| workflow_json = json.dumps(workflow_data, indent=2) | |
| # Create download link | |
| b64 = base64.b64encode(workflow_json.encode()).decode() | |
| filename = f"{workflow_data['name'].replace(' ', '_')}_workflow.json" | |
| href = f'<a href="data:application/json;base64,{b64}" download="{filename}">Download Workflow</a>' | |
| st.success("Workflow exported successfully!") | |
| st.markdown(href, unsafe_allow_html=True) | |
| except Exception as e: | |
| st.error(f"Error exporting workflow: {e}") | |
| # Import workflow section | |
| st.subheader("Import Workflow") | |
| uploaded_file = st.file_uploader("Upload Workflow JSON", type=['json']) | |
| if uploaded_file is not None: | |
| try: | |
| # Load JSON from uploaded file | |
| workflow_json = uploaded_file.read() | |
| workflow_data = json.loads(workflow_json) | |
| # Display workflow info | |
| st.write(f"**Workflow Name:** {workflow_data.get('name', 'Unnamed Workflow')}") | |
| st.write(f"**Date Exported:** {workflow_data.get('date_exported', 'Unknown')}") | |
| if workflow_data.get('dataset') is not None: | |
| st.write(f"**Includes Dataset:** Yes ({workflow_data.get('row_count', 'N/A')} rows × {workflow_data.get('column_count', 'N/A')} columns)") | |
| else: | |
| st.write("**Includes Dataset:** No") | |
| # Import button | |
| if st.button("Import Workflow"): | |
| with st.spinner("Importing workflow..."): | |
| if workflow_data.get('dataset') is not None: | |
| try: | |
| # Decode base64 to CSV | |
| b64_csv = workflow_data['dataset'] | |
| csv_bytes = base64.b64decode(b64_csv) | |
| csv_str = csv_bytes.decode() | |
| # Load CSV into dataframe | |
| csv_buffer = io.StringIO(csv_str) | |
| loaded_df = pd.read_csv(csv_buffer) | |
| # Update session state | |
| st.session_state.df = loaded_df | |
| st.session_state.dataset_name = workflow_data['name'] | |
| st.success(f"Workflow '{workflow_data['name']}' imported successfully with dataset!") | |
| st.rerun() | |
| except Exception as e: | |
| st.error(f"Error importing workflow dataset: {e}") | |
| else: | |
| st.warning("This workflow does not include a dataset. Only workflow metadata was imported.") | |
| except Exception as e: | |
| st.error(f"Error parsing workflow file: {e}") | |
| # Sidebar with educational content | |
| with st.sidebar: | |
| st.title("📚 Collaborative Data Science") | |
| st.markdown(""" | |
| ### Benefits of Collaboration in Data Science | |
| Collaborative data science leads to: | |
| - **Diverse perspectives** that enhance analysis | |
| - **Knowledge sharing** across team members | |
| - **Faster problem solving** through combined expertise | |
| - **Increased reproducibility** with shared workflows | |
| - **Better documentation** for future reference | |
| ### Best Practices for Collaboration | |
| 1. **Document your analysis** | |
| - Include clear descriptions of what you did and why | |
| - Note any assumptions made | |
| - Explain preprocessing steps | |
| 2. **Use version control** | |
| - Save your work regularly | |
| - Track changes over time | |
| - Create branches for experimental analyses | |
| 3. **Standardize workflows** | |
| - Use consistent naming conventions | |
| - Organize projects with clear structure | |
| - Define standard preprocessing steps | |
| 4. **Share meaningful insights** | |
| - Focus on key findings rather than all results | |
| - Use visualizations effectively | |
| - Relate analysis to business questions | |
| 5. **Request specific feedback** | |
| - Ask targeted questions when sharing work | |
| - Be open to constructive criticism | |
| - Incorporate feedback into iterations | |
| ### Data Privacy Considerations | |
| - Always consider data sensitivity when sharing | |
| - Remove or anonymize personally identifiable information | |
| - Follow relevant regulations (GDPR, HIPAA, etc.) | |
| - Use secure methods for sharing sensitive data | |
| """) |