File size: 9,995 Bytes
7a75a62
 
8cdc1d2
 
 
 
e2cd54f
 
 
 
 
8cdc1d2
 
 
e2cd54f
 
 
 
 
 
 
8cdc1d2
 
 
e2cd54f
8cdc1d2
e2cd54f
 
 
 
8cdc1d2
 
 
 
e2cd54f
8cdc1d2
e2cd54f
 
 
 
8cdc1d2
 
 
 
e2cd54f
8cdc1d2
e2cd54f
 
 
 
 
8cdc1d2
 
 
 
e2cd54f
8cdc1d2
e2cd54f
 
 
 
8cdc1d2
 
 
 
e2cd54f
8cdc1d2
e2cd54f
 
 
 
8cdc1d2
 
 
 
e2cd54f
 
 
 
8221fb4
 
 
e2cd54f
8cdc1d2
 
 
e2cd54f
8cdc1d2
e2cd54f
 
 
 
8cdc1d2
 
 
 
e2cd54f
8cdc1d2
e2cd54f
 
 
 
8cdc1d2
 
 
 
e2cd54f
8cdc1d2
e2cd54f
 
 
 
8cdc1d2
 
 
 
e2cd54f
8cdc1d2
e2cd54f
 
 
 
8cdc1d2
 
 
 
e2cd54f
8cdc1d2
e2cd54f
 
 
 
8cdc1d2
 
27facfa
 
8cdc1d2
7a75a62
370c8ad
d8442da
370c8ad
 
c2678e6
370c8ad
d8442da
8cdc1d2
 
 
18ccada
7a75a62
27facfa
7a75a62
c2678e6
 
 
8cdc1d2
c2678e6
cebaf1e
 
c2678e6
7a556c7
c2678e6
 
 
5a61309
d8442da
370c8ad
 
d8442da
7a75a62
370c8ad
7a75a62
 
 
6cba983
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10955dd
 
 
fc7e532
10955dd
 
 
 
 
 
 
 
 
 
 
fc7e532
7a75a62
 
 
c3bbdce
7a75a62
c3bbdce
 
 
8cdc1d2
 
27facfa
10955dd
 
44fcdc8
 
27facfa
7a75a62
c3bbdce
7a75a62
 
 
e2cd54f
27facfa
 
10955dd
 
7a75a62
27facfa
2c4d71e
 
96304a2
10955dd
 
7a75a62
c3bbdce
7a75a62
 
b095a64
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
import streamlit as st

# Predefined analysis tasks and visualization types
PREDEFINED_ANALYSIS = {
    "Basic Statistics": {
        "Description": "Generate basic statistics summary for the dataset.",
        "Function": "show_basic_statistics",
        "Code": """
def show_basic_statistics(df):
    st.write(df.describe())
"""
    },
    "Correlation Heatmap": {
        "Description": "Generate a correlation heatmap for numeric columns.",
        "Function": "show_correlation_heatmap",
        "Code": """
def show_correlation_heatmap(df):
    import seaborn as sns
    st.write(df.corr())
    st.write(sns.heatmap(df.corr(), annot=True, cmap='coolwarm'))
"""
    },
    "Histogram": {
        "Description": "Generate a histogram for a selected numeric column.",
        "Function": "show_histogram",
        "Code": """
def show_histogram(df):
    import plotly.express as px
    selected_column = st.selectbox("Select a numeric column for the histogram", df.select_dtypes(include='number').columns)
    st.write(px.histogram(df, x=selected_column))
"""
    },
    "Box Plot": {
        "Description": "Generate a box plot for a selected numeric column.",
        "Function": "show_box_plot",
        "Code": """
def show_box_plot(df):
    import plotly.express as px
    selected_column = st.selectbox("Select a numeric column for the box plot", df.select_dtypes(include='number').columns)
    st.write(px.box(df, y=selected_column))
"""
    },
    "Scatter Plot": {
        "Description": "Generate a scatter plot for two selected numeric columns.",
        "Function": "show_scatter_plot",
        "Code": """
def show_scatter_plot(df):
    import plotly.express as px
    x_column = st.selectbox("Select X-axis column", df.select_dtypes(include='number').columns)
    y_column = st.selectbox("Select Y-axis column", df.select_dtypes(include='number').columns)
    st.write(px.scatter(df, x=x_column, y=y_column))
"""
    },
    "Line Plot": {
        "Description": "Generate a line plot for a selected numeric column.",
        "Function": "show_line_plot",
        "Code": """
def show_line_plot(df):
    import plotly.express as px
    selected_column = st.selectbox("Select a numeric column for the line plot", df.select_dtypes(include='number').columns)
    st.write(px.line(df, x=df.index, y=selected_column))
"""
    },
    "Bar Chart": {
        "Description": "Generate a bar chart for a selected categorical column.",
        "Function": "show_bar_chart",
        "Code": """
def show_bar_chart(df):
    import plotly.express as px
    selected_column = st.selectbox("Select a categorical column for the bar chart", df.select_dtypes(include='object').columns)
    st.write(px.bar(df, x=selected_column))
"""
    },
    "Pair Plot": {
        "Description": "Generate a pair plot for pairwise relationships between numeric columns.",
        "Function": "show_pair_plot",
        "Code": """
def show_pair_plot(df):
    import seaborn as sns
    numeric_columns = df.select_dtypes(include='number').columns
    selected_columns = st.multiselect("Select numeric columns for the pair plot", numeric_columns)
    st.write(sns.pairplot(df[selected_columns]))
"""
    },
    "Distribution Plot": {
        "Description": "Generate a distribution plot for a selected numeric column.",
        "Function": "show_distribution_plot",
        "Code": """
def show_distribution_plot(df):
    import seaborn as sns
    selected_column = st.selectbox("Select a numeric column for the distribution plot", df.select_dtypes(include='number').columns)
    st.write(sns.displot(df[selected_column], kde=True))
"""
    },
    "Count Plot": {
        "Description": "Generate a count plot for a selected categorical column.",
        "Function": "show_count_plot",
        "Code": """
def show_count_plot(df):
    import seaborn as sns
    selected_column = st.selectbox("Select a categorical column for the count plot", df.select_dtypes(include='object').columns)
    st.write(sns.countplot(data=df, x=selected_column))
"""
    },
    "Pie Chart": {
        "Description": "Generate a pie chart for a selected categorical column.",
        "Function": "show_pie_chart",
        "Code": """
def show_pie_chart(df):
    import plotly.express as px
    selected_column = st.selectbox("Select a categorical column for the pie chart", df.select_dtypes(include='object').columns)
    st.write(px.pie(df, names=selected_column))
"""
    },
    "Area Plot": {
        "Description": "Generate an area plot for a selected numeric column.",
        "Function": "show_area_plot",
        "Code": """
def show_area_plot(df):
    import plotly.express as px
    selected_column = st.selectbox("Select a numeric column for the area plot", df.select_dtypes(include='number').columns)
    st.write(px.area(df, x=df.index, y=selected_column))
"""
    },
    "Violin Plot": {
        "Description": "Generate a violin plot for a selected numeric column.",
        "Function": "show_violin_plot",
        "Code": """
def show_violin_plot(df):
    import plotly.express as px
    selected_column = st.selectbox("Select a numeric column for the violin plot", df.select_dtypes(include='number').columns)
    st.write(px.violin(df, y=selected_column))
"""
    },
}

def generate_streamlit_app_code(app_title, app_subtitle, side_panel_title, analysis_tasks, requirements):
    # Generate Python code for the Streamlit app
    # Ensure analysis functions are correctly indented at the same level as the main function
    analysis_functions_code = "\n    ".join([PREDEFINED_ANALYSIS[task]['Code'].replace("\n", "\n    ") for task in analysis_tasks])
    # Ensure calls to analysis functions are correctly indented within the main function and only executed if df is not empty
    analysis_tasks_code = "    if not df.empty:\n" + "\n".join([f"        {PREDEFINED_ANALYSIS[task]['Function']}(df)" for task in analysis_tasks])
    
    # Generate the full code for the Streamlit app
    code = f"""import streamlit as st
import pandas as pd
import seaborn as sns
import plotly.express as px
import matplotlib.pyplot as plt


def main():
    st.title("{app_title}")
    st.subheader("{app_subtitle}")
    st.sidebar.title("{side_panel_title}")

    uploaded_file = st.file_uploader("Upload a CSV file", type=["csv"])
    df = pd.DataFrame()  # Initialize an empty DataFrame

    if uploaded_file is not None:
        @st.cache_data  # Use the correct caching decorator
        def load_data(uploaded_file):
            return pd.read_csv(uploaded_file)
        df = load_data(uploaded_file)

{analysis_functions_code}

    # Analysis task calls, only executed if df is not empty
{analysis_tasks_code}

main()  # Call the main function to run the app
"""
    return code

# Define required libraries for each predefined analysis task
TASK_REQUIREMENTS = {
    "Basic Statistics": ["pandas", "streamlit"],
    "Correlation Heatmap": ["pandas", "streamlit", "seaborn"],
    "Histogram": ["pandas", "streamlit", "plotly"],
    "Box Plot": ["pandas", "streamlit", "plotly"],
    "Scatter Plot": ["pandas", "streamlit", "plotly"],
    "Line Plot": ["pandas", "streamlit", "plotly"],
    "Bar Chart": ["pandas", "streamlit", "plotly"],
    "Pair Plot": ["pandas", "streamlit", "seaborn"],
    "Distribution Plot": ["pandas", "streamlit", "seaborn"],
    "Count Plot": ["pandas", "streamlit", "seaborn"],
    "Pie Chart": ["pandas", "streamlit", "plotly"],
    "Area Plot": ["pandas", "streamlit", "plotly"],
    "Violin Plot": ["pandas", "streamlit", "plotly"]
}

def generate_requirements(selected_tasks):
    # Set to store all unique required libraries
    required_libraries = {"streamlit", "pandas", "matplotlib", "seaborn", "plotly"}  # Default libraries are always included

    # Add libraries for each selected task
    for task in selected_tasks:
        required_libraries.update(TASK_REQUIREMENTS.get(task, []))

    # Convert set to sorted list for consistent order
    requirements_list = sorted(list(required_libraries))

    # Format list into string to place in requirements.txt format
    return "\n".join(requirements_list)


def main():
    st.title("Streamlit App Generator")

    # User inputs for app parameters
    app_title = st.text_input("Enter your Streamlit app title:")
    app_subtitle = st.text_input("Enter your Streamlit app subtitle:")
    side_panel_title = st.text_input("Enter your Streamlit app side panel title:")

    # Select predefined analysis tasks
    selected_tasks = st.multiselect("Select predefined analysis tasks to include:", list(PREDEFINED_ANALYSIS.keys()))

    # Automatically generate requirements.txt content based on selected tasks
    auto_requirements = generate_requirements(selected_tasks)
    # Here, the default requirements are always included, and additional requirements are added based on selected tasks
    requirements = st.text_area("Enter requirements.txt content (optional, defaults included):", value=auto_requirements)

    if st.button("Generate and Download"):
        if app_title:
            # Write generated code to a .py file
            file_path = f"{app_title.replace(' ', '_').lower()}_app.py"
            with open(file_path, "w") as f:
                f.write(generate_streamlit_app_code(app_title, app_subtitle, side_panel_title, selected_tasks, requirements))

            # Write requirements.txt file
            with open("requirements.txt", "w") as req_file:
                req_file.write(requirements)

            # Download the generated files
            with open(file_path, "rb") as file:
                btn = st.download_button(label="Download your Streamlit app", data=file, file_name=file_path)
                
            with open("requirements.txt", "rb") as req_file:
                btn_req = st.download_button(label="Download requirements.txt", data=req_file, file_name="requirements.txt")
        else:
            st.warning("Please enter a title for your Streamlit app.")

if __name__ == "__main__":
    main()