File size: 17,578 Bytes
e962e08
 
 
 
 
0c3cbdf
fb89c2f
e962e08
be26401
 
 
 
 
 
 
 
 
e962e08
be26401
 
 
 
 
 
e962e08
be26401
 
 
e962e08
fb89c2f
 
 
be26401
 
 
 
 
 
 
 
 
 
 
e1629ce
be26401
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e1629ce
be26401
 
 
 
 
 
 
 
 
 
e1629ce
be26401
 
 
 
 
 
 
 
 
 
 
e1629ce
be26401
 
 
 
e1629ce
be26401
 
 
 
e1629ce
be26401
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e1629ce
be26401
 
e1629ce
be26401
 
 
 
e1629ce
be26401
 
 
e1629ce
be26401
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e1629ce
be26401
 
 
e1629ce
be26401
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e1629ce
be26401
 
e1629ce
be26401
 
 
 
 
 
 
 
 
 
 
e1629ce
be26401
 
 
 
e1629ce
be26401
 
 
 
 
 
 
 
 
 
 
e1629ce
be26401
 
 
e1629ce
be26401
 
 
 
e1629ce
be26401
 
 
 
 
 
 
 
 
e1629ce
be26401
 
 
 
 
 
e1629ce
be26401
 
e1629ce
be26401
 
 
 
 
 
 
e1629ce
be26401
 
 
e1629ce
be26401
 
 
 
e1629ce
be26401
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e1629ce
be26401
 
 
 
e1629ce
be26401
 
 
 
 
 
 
 
 
 
e1629ce
 
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
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
# Import necessary libraries
import streamlit as st
import pandas as pd
import altair as alt
import matplotlib.pyplot as plt
import seaborn as sns
from scipy.stats import zscore

# Function to load and clean data
@st.cache_data
def load_and_clean_data(file_path):
    # Load data
    df_kiva_loans = pd.read_csv(file_path)

    # Clean data
    df_kiva_loans = df_kiva_loans.drop(['use', 'disbursed_time', 'funded_time', 'posted_time', 'tags'], axis=1)
    df_kiva_loans.dropna(subset=['partner_id', 'borrower_genders'], inplace=True)

    # Calculate Z-scores
    z_scores = zscore(df_kiva_loans['funded_amount'])
    df_kiva_loans['outlier_funded_amount'] = (z_scores > 3) | (z_scores < -3)
    df_kiva_loans_cleaned = df_kiva_loans[~df_kiva_loans['outlier_funded_amount']]
    
    return df_kiva_loans_cleaned

# Load the cleaned data
file_path = 'kiva_loans.csv'
df_kiva_loans_cleaned = load_and_clean_data(file_path)

# Streamlit App Title
st.title('BDS24_Weekly_Assignment_Week 2 | Tryfonas Karmiris')

# Sidebar for navigation
st.sidebar.title("Navigation")
page = st.sidebar.radio("Select a page:", ["Introduction", "Data Overview", "Top Values by Selected Variable", "Repayment Interval by Selected Variable", "Country Comparison Deepdive", "Sector Comparison Deepdive"])

# Introduction Page
if page == "Introduction":
    st.subheader("Introduction")
    st.write("""

        This application provides insights into Kiva loans data. 

        You can explore the distribution of funded amounts, 

        analyze top values by selected variables, and visualize 

        relationships between funded amounts and various factors such as Countries and Sectors that the loans were funded.

    """)

# Data Overview Page
elif page == "Data Overview":
    st.subheader("Data Overview")
    st.write("Here is a preview of the cleaned Kiva loans data:")
    
    # Display the cleaned data table
    st.table(df_kiva_loans_cleaned.head())

    # Distribution of Funded Amounts
    st.subheader('Distribution of Funded Amounts')
    chart = alt.Chart(df_kiva_loans_cleaned).mark_bar().encode(
        alt.X('funded_amount', bin=alt.Bin(maxbins=50)),  # Use funded_amount for distribution
        y='count()',
    ).properties(
        title='Distribution of Funded Amounts'
    )
    st.altair_chart(chart, use_container_width=True)
    st.write("This chart shows the distribution of funded amounts for Kiva loans. The x-axis represents the funded amount, while the y-axis shows the count of loans that fall within each bin. As you can see most of the loans are low valued with most of them being in the range of 100 and 500")

# Page 3: Top Values by Selected Variable
elif page == "Top Values by Selected Variable":
    st.subheader('Top Values by Selected Variable')

    # Dropdown for plot type
    plot_type = st.selectbox("Select Variable to Display", ['country', 'repayment_interval', 'sector'])

    # Slider to select the number of top values to display
    num_columns = st.slider(
        "Select Number of Columns to Display on the Chart",
        min_value=5,
        max_value=50,
        value=10,  # default value
        step=1
    )

    # Select the top values based on the selected variable and number of columns
    if plot_type == 'country':
        top_values = df_kiva_loans_cleaned.groupby('country')['funded_amount'].agg(['sum', 'count']).nlargest(num_columns, 'sum').reset_index()
        x_column = 'country'
        count_column = 'count'
        description = f"This chart displays the top {num_columns} countries by total funded amount. The blue bars represent the total funded amount, while the red line indicates the count of loans. In general Phillipines is the country with the most loans followed by Kenya and El Salvador."
    elif plot_type == 'repayment_interval':
        top_values = df_kiva_loans_cleaned.groupby('repayment_interval')['funded_amount'].agg(['sum', 'count']).nlargest(num_columns, 'sum').reset_index()
        x_column = 'repayment_interval'
        count_column = 'count'
        description = f"This chart shows the top {num_columns} repayment intervals by total funded amount. The blue bars represent the total funded amount, while the red line indicates the count of loans. Most of the loans are funded with a monthly repayment interval, where the bullet repayment is an unsusal choice"
    else:  # sector
        top_values = df_kiva_loans_cleaned.groupby('sector')['funded_amount'].agg(['sum', 'count']).nlargest(num_columns, 'sum').reset_index()
        x_column = 'sector'
        count_column = 'count'
        description = f"This chart illustrates the top {num_columns} sectors by total funded amount. The blue bars represent the total funded amount, while the red line indicates the count of loans. Most loans are funded to the Aggriculture Sector with Food and Retail completing the first three. Looks like that if the sector of the business is close to Primary production or its Basic Necessities(food) "

    # Display description
    st.write(description)

    # Create a dual-axis bar plot using Matplotlib
    fig, ax1 = plt.subplots(figsize=(12, 9))
    plt.xticks(rotation=90)

    # Bar plot for funded_amount
    color = 'tab:blue'
    ax1.set_xlabel(x_column.replace("_", " ").title())
    ax1.set_ylabel('Funded Amount', color=color)
    ax1.bar(top_values[x_column], top_values['sum'], color=color, alpha=0.6, label='Funded Amount')
    ax1.tick_params(axis='y', labelcolor=color)

    # Create a second y-axis for count
    ax2 = ax1.twinx()
    color = 'tab:red'
    ax2.set_ylabel('Count', color=color)
    ax2.plot(top_values[x_column], top_values[count_column], color=color, marker='o', linestyle='-', linewidth=2, label='Count')
    ax2.tick_params(axis='y', labelcolor=color)

    # Add titles and labels
    plt.title(f'Top {num_columns} by {plot_type.replace("_", " ").title()}')
    fig.tight_layout()
    st.pyplot(fig)

    # Boxplot after the dual-axis plot
    st.subheader('Funded Amount vs. Selected Variable')

    # Filter the data based on the selected variable and number of top values
    if plot_type == 'sector':
        top_values_boxplot = df_kiva_loans_cleaned.groupby('sector')['funded_amount'].agg('sum').nlargest(num_columns).index
        filtered_df_boxplot = df_kiva_loans_cleaned[df_kiva_loans_cleaned['sector'].isin(top_values_boxplot)]
    elif plot_type == 'country':
        top_values_boxplot = df_kiva_loans_cleaned.groupby('country')['funded_amount'].agg('sum').nlargest(num_columns).index
        filtered_df_boxplot = df_kiva_loans_cleaned[df_kiva_loans_cleaned['country'].isin(top_values_boxplot)]
    else:  # repayment_interval
        filtered_df_boxplot = df_kiva_loans_cleaned

    # Create a boxplot
    fig, ax = plt.subplots(figsize=(12, 6))
    if plot_type != 'repayment_interval':
        top_values_sorted = df_kiva_loans_cleaned.groupby(plot_type)['funded_amount'].agg('sum').nlargest(num_columns).index
        sns.boxplot(x=plot_type, y='funded_amount', data=filtered_df_boxplot, order=top_values_sorted, ax=ax)
        st.write(f"This boxplot shows the distribution of funded amounts for the top {num_columns} {plot_type.replace('_', ' ')}. It provides insights into the spread and outliers of funded amounts.")
    else:
        sns.boxplot(x=plot_type, y='funded_amount', data=filtered_df_boxplot, ax=ax)
        st.write(f"This boxplot shows the distribution of funded amounts for the top {num_columns} {plot_type.replace('_', ' ')}. It provides insights into the spread and outliers of funded amounts.")

    plt.title('Funded Amount by Selected Variable')
    plt.xlabel(plot_type)
    plt.ylabel('Funded Amount')
    plt.xticks(rotation=90)
    st.pyplot(fig)

    # Display description for boxplot
    

# Page 4: Other Plots
elif page == "Repayment Interval by Selected Variable":
    st.subheader('Repayment Interval by Selected Variable')

    # Dropdown for selecting variable for Seaborn countplot
    plot_var = st.selectbox("Select Variable for Countplot", ['sector', 'country'])

    # Slider to select the number of top values to display for Seaborn countplot
    num_top_values = st.slider(
        "Select Number of Top Values to Display",
        min_value=5,
        max_value=50,
        value=10,  # default value
        step=1
    )

    # Filter the data based on the selected variable and number of top values
    if plot_var == 'sector':
        top_values_plot = df_kiva_loans_cleaned.groupby('sector')['funded_amount'].agg('count').nlargest(num_top_values).index
        filtered_df_plot = df_kiva_loans_cleaned[df_kiva_loans_cleaned['sector'].isin(top_values_plot)]
        description = f"This countplot shows the distribution of repayment intervals for the top {num_top_values} sectors based on the number of loans. In terms of sectors Agriculture got the most monthly repayment loans followed by food. Also a lot of irregulars were in the Food, Retail and Agriculture sectors, which again confirms that loans for first necessities are given more easily. "
    elif plot_var == 'country':
        top_values_plot = df_kiva_loans_cleaned.groupby('country')['funded_amount'].agg('count').nlargest(num_top_values).index
        filtered_df_plot = df_kiva_loans_cleaned[df_kiva_loans_cleaned['country'].isin(top_values_plot)]
        description = f"This countplot illustrates the distribution of repayment intervals for the top {num_top_values} countries based on the number of loans. In terms of countries the Phillipines had a great number of Irregular loans."

    # Display description
    st.write(description)

    # Create a count plot
    fig, ax = plt.subplots(figsize=(10, 6))

    # Count the occurrences of repayment intervals for the filtered data
    count_data = filtered_df_plot.groupby('repayment_interval')[plot_var].value_counts().unstack(fill_value=0)

    # Calculate total counts for sorting
    total_counts = count_data.sum(axis=1)

    # Sort the repayment intervals based on the total count of loans in descending order
    sorted_index = total_counts.sort_values(ascending=False).index
    count_data = count_data.loc[sorted_index]

    # Create a grouped bar plot
    count_data.plot(kind='bar', ax=ax, position=0, width=0.8)
    plt.title(f'Repayment Interval by {plot_var.replace("_", " ").title()}')
    plt.xlabel('Repayment Interval')
    plt.ylabel('Count of Loans')
    plt.xticks(rotation=45)
    plt.legend(title=plot_var.replace("_", " ").title(), bbox_to_anchor=(1.05, 1), loc='upper left')
    st.pyplot(fig)




# Page 5: Country Comparison
elif page == "Country Comparison Deepdive":
    st.subheader("Country Comparison Deepdive")

    # Multi-select for countries
    selected_countries = st.multiselect("Select Countries to Compare(Please select one or more)", options=df_kiva_loans_cleaned['country'].unique())

    # Option to choose between count or sum of funded amounts
    aggregation_option = st.radio("Select Aggregation Type:", ("Count of Loans", "Summary of Funded Amount"))

    if selected_countries:
        # Filter the data based on selected countries
        filtered_data = df_kiva_loans_cleaned[df_kiva_loans_cleaned['country'].isin(selected_countries)]

        # Create a combined bar plot for sector summary
        st.subheader("Total Funded Amounts by Sector for Selected Countries")
        if aggregation_option == "Sum":
            sector_summary = filtered_data.groupby(['country', 'sector']).agg(
                total_funded_amount=('funded_amount', 'sum')
            ).reset_index()
            st.write("This graph shows the total funded amount in each Sector for the selected Countries by the user.")
        else:  # Count
            sector_summary = filtered_data.groupby(['country', 'sector']).agg(
                total_funded_amount=('funded_amount', 'count')
            ).reset_index()
            st.write("This graph shows the number of loans in each Sector for the selected Countries by the user.")

        fig, ax = plt.subplots(figsize=(12, 6))
        sns.barplot(x='sector', y='total_funded_amount', hue='country', data=sector_summary, ax=ax)
        plt.title(f'Total Funded Amount by Sector for Selected Countries ({aggregation_option})')
        plt.xlabel('Sector')
        plt.ylabel('Total Funded Amount' if aggregation_option == "Sum" else 'Count of Loans')
        plt.xticks(rotation=45)
        st.pyplot(fig)

        # Create a combined bar plot for repayment summary
        st.subheader("Total Funded Amounts by Repayment Interval for Selected Countries")
        if aggregation_option == "Summary of Funded Amount":
            repayment_summary = filtered_data.groupby(['country', 'repayment_interval']).agg(
                total_funded_amount=('funded_amount', 'sum')
            ).reset_index()
            st.write("This graph shows the total funded amount in each Repayment interval for the selected Countries by the user.")
        else:  # Count
            repayment_summary = filtered_data.groupby(['country', 'repayment_interval']).agg(
                total_funded_amount=('funded_amount', 'count')
            ).reset_index()
            st.write("This graph shows the number of loans in each Repayment interval for the selected Countries by the user.")

        fig, ax = plt.subplots(figsize=(12, 6))
        sns.barplot(x='repayment_interval', y='total_funded_amount', hue='country', data=repayment_summary, ax=ax)
        plt.title(f'Total Funded Amount by Repayment Interval for Selected Countries ({aggregation_option})')
        plt.xlabel('Repayment Interval')
        plt.ylabel('Total Funded Amount' if aggregation_option == "Sum" else 'Count of Loans')
        plt.xticks(rotation=45)
        st.pyplot(fig)
    else:
        st.write("Please select one or more countries to compare from the dropdown above.")

# Page 6: Sector Comparison
elif page == "Sector Comparison Deepdive":
    st.subheader("Sector Comparison Deepdive")

    # Multi-select for sectors
    selected_sectors = st.multiselect("Select Sectors to Compare (Please select one or more)", options=df_kiva_loans_cleaned['sector'].unique())

    # Option to choose between count or sum of funded amounts
    aggregation_option = st.radio("Select Aggregation Type:", ("Count of Loans", "Summmary of Funded Amount"))

    if selected_sectors:
        # Filter the data based on selected sectors
        filtered_data = df_kiva_loans_cleaned[df_kiva_loans_cleaned['sector'].isin(selected_sectors)]

        # Create a combined bar plot for sector summary by country
        st.subheader("Total Funded Amounts by Country for Selected Sectors")
        if aggregation_option == "Summary of Funded Amount":
            country_summary = filtered_data.groupby(['country', 'sector']).agg(
                total_funded_amount=('funded_amount', 'sum')
            ).reset_index()
            st.write("This graph shows the total funded amount in each Country, for the selected Sectors by the user.")
        else:  # Count
            country_summary = filtered_data.groupby(['country', 'sector']).agg(
                total_funded_amount=('funded_amount', 'count')
            ).reset_index()
            st.write("This graph shows the number of loans in each Country, for the selected Sectors by the user.")

        fig, ax = plt.subplots(figsize=(12, 6))
        sns.barplot(x='country', y='total_funded_amount', hue='sector', data=country_summary, ax=ax)
        plt.title(f'Total Funded Amount by Country for Selected Sectors ({aggregation_option})')
        plt.xlabel('Country')
        plt.ylabel('Total Funded Amount' if aggregation_option == "Sum" else 'Count of Loans')
        plt.legend(title='Sector', bbox_to_anchor=(1.05, 1), loc='upper left')
        plt.xticks(rotation=90)
        st.pyplot(fig)

        # Create a combined bar plot for repayment summary
        st.subheader("Total Funded Amounts by Repayment Interval for Selected Sectors")
        if aggregation_option == "Sum":
            repayment_summary = filtered_data.groupby(['repayment_interval', 'sector']).agg(
                total_funded_amount=('funded_amount', 'sum')
            ).reset_index()
            st.write("This graph shows the funded amount in each Repayment interval for the selected Sectors  by the user.")
        else:  # Count
            repayment_summary = filtered_data.groupby(['repayment_interval', 'sector']).agg(
                total_funded_amount=('funded_amount', 'count')
            ).reset_index()
            st.write("This graph shows the number of loans in each Repayment interval for the selected Sectors by the user.")

        fig, ax = plt.subplots(figsize=(12, 6))
        sns.barplot(x='repayment_interval', y='total_funded_amount', hue='sector', data=repayment_summary, ax=ax)
        plt.title(f'Total Funded Amount by Repayment Interval for Selected Sectors ({aggregation_option})')
        plt.xlabel('Repayment Interval')
        plt.ylabel('Total Funded Amount' if aggregation_option == "Sum" else 'Count of Loans')
        plt.legend(title='Sector', bbox_to_anchor=(1.05, 1), loc='upper left')
        plt.xticks(rotation=90)
        st.pyplot(fig)
    else:
        st.write("Please select one or more countries to compare from the dropdown above.")