Update app.py
Browse files
app.py
CHANGED
@@ -1,181 +1,181 @@
|
|
1 |
-
from flask import Flask, render_template, request, jsonify
|
2 |
-
import pandas as pd
|
3 |
-
import plotly.express as px
|
4 |
-
import plotly.graph_objects as go
|
5 |
-
import plotly.io as pio
|
6 |
-
import joblib
|
7 |
-
import numpy as np
|
8 |
-
|
9 |
-
app = Flask(__name__)
|
10 |
-
|
11 |
-
url='https://drive.google.com/file/d/1_vd4HISZB2h2--CiXKezeWDXHHo2fY23/view?usp=sharing'
|
12 |
-
df = pd.read_csv('https://drive.usercontent.google.com/download?id={}&export=download&authuser=0&confirm=t'.format(url.split('/')[-2]))
|
13 |
-
|
14 |
-
for column in ['State', 'District', 'Crop', 'Season']:
|
15 |
-
df[column] = df[column].str.strip()
|
16 |
-
|
17 |
-
# Load the model for predictions
|
18 |
-
model_filename = 'lgb_model_cropforecastinghyperparamters__33333.pkl'
|
19 |
-
model = joblib.load(model_filename)
|
20 |
-
|
21 |
-
# Use a 2% sample for faster processing
|
22 |
-
sampled_df = df.sample(frac=0.02, random_state=42)
|
23 |
-
|
24 |
-
@app.route('/')
|
25 |
-
def index():
|
26 |
-
states = sampled_df['State'].unique()
|
27 |
-
crops = sampled_df['Crop'].unique()
|
28 |
-
seasons = sampled_df['Season'].unique()
|
29 |
-
return render_template('index.html', states=states, crops=crops, seasons=seasons)
|
30 |
-
|
31 |
-
@app.route('/filter_districts', methods=['POST'])
|
32 |
-
def filter_districts():
|
33 |
-
state = request.form['state']
|
34 |
-
districts = sampled_df[sampled_df['State'] == state]['District'].unique()
|
35 |
-
return jsonify({'districts': list(districts)})
|
36 |
-
|
37 |
-
@app.route('/predict', methods=['POST'])
|
38 |
-
def predict():
|
39 |
-
state = request.form['state']
|
40 |
-
district = request.form['district']
|
41 |
-
crop_year = int(request.form['crop_year'])
|
42 |
-
season = request.form['season']
|
43 |
-
crop = request.form['crop']
|
44 |
-
area = float(request.form['area'])
|
45 |
-
|
46 |
-
# Prepare input for prediction
|
47 |
-
input_data = pd.DataFrame({
|
48 |
-
'State': [state],
|
49 |
-
'District': [district],
|
50 |
-
'Crop_Year': [crop_year],
|
51 |
-
'Season': [season],
|
52 |
-
'Crop': [crop],
|
53 |
-
'Area': [area]
|
54 |
-
})
|
55 |
-
|
56 |
-
# Ensure consistent categories with the original DataFrame
|
57 |
-
input_data['State'] = input_data['State'].astype(pd.CategoricalDtype(categories=df['State'].unique()))
|
58 |
-
input_data['District'] = input_data['District'].astype(pd.CategoricalDtype(categories=df['District'].unique()))
|
59 |
-
input_data['Season'] = input_data['Season'].astype(pd.CategoricalDtype(categories=df['Season'].unique()))
|
60 |
-
input_data['Crop'] = input_data['Crop'].astype(pd.CategoricalDtype(categories=df['Crop'].unique()))
|
61 |
-
|
62 |
-
# Make prediction
|
63 |
-
prediction = model.predict(input_data)[0]
|
64 |
-
prediction_tons = max(0, round(prediction, 2)) # Ensure prediction is non-negative
|
65 |
-
|
66 |
-
# Calculate production/area ratio
|
67 |
-
nearest_area = find_nearest_area(state, district)
|
68 |
-
production_ratio = round((prediction_tons / nearest_area), 2)
|
69 |
-
ratio_category = categorize_production_ratio(production_ratio)
|
70 |
-
|
71 |
-
# Generate updated graphs based on the selected state and district
|
72 |
-
pie_chart = generate_pie_chart(state, district, crop)
|
73 |
-
area_vs_production = generate_area_vs_production(state, district)
|
74 |
-
season_vs_production = generate_season_vs_production(state, district)
|
75 |
-
top_states_by_production = generate_top_states_plot()
|
76 |
-
yearly_violin_plot = generate_yearly_violin_plot()
|
77 |
-
crop_year_vs_production = generate_crop_year_vs_production(state, district)
|
78 |
-
|
79 |
-
# Create gauge chart for the production ratio
|
80 |
-
gauge_chart = generate_gauge_chart(production_ratio, ratio_category)
|
81 |
-
|
82 |
-
# Hardcoded suggestions based on production ratio
|
83 |
-
suggestions = generate_suggestions(ratio_category, crop, district)
|
84 |
-
|
85 |
-
return render_template('output.html',
|
86 |
-
prediction=prediction_tons,
|
87 |
-
ratio=production_ratio,
|
88 |
-
pie_chart_html=pio.to_html(pie_chart, full_html=False),
|
89 |
-
season_vs_production_html=pio.to_html(season_vs_production, full_html=False),
|
90 |
-
area_vs_production_html=pio.to_html(area_vs_production, full_html=False),
|
91 |
-
top_states_html=pio.to_html(top_states_by_production, full_html=False),
|
92 |
-
yearly_violin_plot_html=pio.to_html(yearly_violin_plot, full_html=False),
|
93 |
-
crop_year_vs_production_html=pio.to_html(crop_year_vs_production, full_html=False),
|
94 |
-
gauge_chart_html=pio.to_html(gauge_chart, full_html=False),
|
95 |
-
suggestions=suggestions)
|
96 |
-
|
97 |
-
|
98 |
-
def find_nearest_area(state, district):
|
99 |
-
# Calculate the nearest similar area for the district using average
|
100 |
-
district_data = sampled_df[(sampled_df['State'] == state) & (sampled_df['District'] == district)]
|
101 |
-
return district_data['Area'].mean()
|
102 |
-
|
103 |
-
def categorize_production_ratio(ratio):
|
104 |
-
if ratio <= 2:
|
105 |
-
return 'Very Low'
|
106 |
-
elif ratio <= 4:
|
107 |
-
return 'Low'
|
108 |
-
elif ratio <= 6:
|
109 |
-
return 'Normal'
|
110 |
-
elif ratio <= 8:
|
111 |
-
return 'High'
|
112 |
-
else:
|
113 |
-
return 'Very High'
|
114 |
-
|
115 |
-
def generate_suggestions(category, crop, district):
|
116 |
-
suggestions = {
|
117 |
-
'Very Low': f"Increase soil nutrients and irrigation efficiency. Consider crop rotation strategies. {crop} is not suitable for {district} based on the given conditions and season. Try advanced farming methods or consider growing alternative crops that are better suited to this region.",
|
118 |
-
'Low': f"Optimize seed selection and planting techniques. {crop} is somewhat suitable for {district}, but production may be low. Monitor soil moisture regularly and apply precise farming techniques. Current strategies may need improvement for better yields.",
|
119 |
-
'Normal': f"Maintain current practices but focus on improving pest control and irrigation. {crop} is generally performing well in {district}. Production and profit depend heavily on farming practices and weather conditions, but there is potential for increased revenue.",
|
120 |
-
'High': f"Consider diversifying crops or expanding production. Explore more efficient harvesting methods to optimize yield and profitability. {crop} thrives in {district}, and with better mechanization or workforce management, you can further boost production and income potential.",
|
121 |
-
'Very High': f"{crop} is performing exceptionally well in {district}. Explore export opportunities to maximize profitability. Optimize production processes to sustain high yields while minimizing additional inputs. Consider expanding into new markets, and explore ways to reduce production costs, such as through precision farming or automation."
|
122 |
-
}
|
123 |
-
return suggestions.get(category, "No suggestions available.")
|
124 |
-
|
125 |
-
|
126 |
-
def generate_gauge_chart(ratio, category):
|
127 |
-
colors = ["#ff0000", "#ff6666", "#ffa500", "#ffff00", "#32cd32"]
|
128 |
-
fig = go.Figure(go.Indicator(
|
129 |
-
mode="gauge+number+delta",
|
130 |
-
value=ratio,
|
131 |
-
title={'text': "Production Ratio"},
|
132 |
-
delta={'reference': 5},
|
133 |
-
gauge={'axis': {'range': [None, 10]},
|
134 |
-
'bar': {'color': "darkblue"},
|
135 |
-
'steps': [{'range': [0, 2], 'color': colors[0]},
|
136 |
-
{'range': [2, 4], 'color': colors[1]},
|
137 |
-
{'range': [4, 6], 'color': colors[2]},
|
138 |
-
{'range': [6, 8], 'color': colors[3]},
|
139 |
-
{'range': [8, 10], 'color': colors[4]}]}))
|
140 |
-
return fig
|
141 |
-
|
142 |
-
def generate_pie_chart(state, district, crop):
|
143 |
-
filtered_data = sampled_df[(sampled_df['State'] == state) & (sampled_df['District'] == district)]
|
144 |
-
crop_data = filtered_data.groupby('Crop')['Production'].sum().reset_index()
|
145 |
-
crop_data['Percentage'] = (crop_data['Production'] / crop_data['Production'].sum()) * 100
|
146 |
-
crop_data = crop_data[crop_data['Percentage'] > 3]
|
147 |
-
fig = px.pie(crop_data, names='Crop', values='Production', title='Popular Crops in the Given Region')
|
148 |
-
return fig
|
149 |
-
|
150 |
-
def generate_season_vs_production(state, district):
|
151 |
-
filtered_data = sampled_df[(sampled_df['State'] == state) & (sampled_df['District'] == district)]
|
152 |
-
fig = px.bar(filtered_data, x='Season', y='Production', title='Season vs Production (Sum for All Crops)')
|
153 |
-
fig.update_traces(marker_color='darkblue')
|
154 |
-
return fig
|
155 |
-
|
156 |
-
def generate_area_vs_production(state, district):
|
157 |
-
filtered_data = sampled_df[(sampled_df['State'] == state) & (sampled_df['District'] == district)]
|
158 |
-
fig = px.density_heatmap(filtered_data, x='Area', y='Production', title='Area vs Production (Hexbin Plot)',
|
159 |
-
range_x=[0, 10000], nbinsx=5)
|
160 |
-
return fig
|
161 |
-
|
162 |
-
def generate_top_states_plot():
|
163 |
-
state_data = sampled_df.groupby('State')['Production'].sum().reset_index()
|
164 |
-
top_states = state_data.nlargest(10, 'Production')
|
165 |
-
fig = px.bar(top_states, x='State', y='Production', title='Top 10 States by Production (Overall)')
|
166 |
-
return fig
|
167 |
-
|
168 |
-
def generate_yearly_violin_plot():
|
169 |
-
filtered_data = sampled_df[sampled_df['Crop_Year'] >= 2014]
|
170 |
-
fig = px.violin(filtered_data, x='Crop_Year', y='Production', title='Violin Plot: Overall Production (2014-2023)')
|
171 |
-
return fig
|
172 |
-
|
173 |
-
def generate_crop_year_vs_production(state, district):
|
174 |
-
filtered_data = sampled_df[sampled_df['Crop_Year'] >= 2014]
|
175 |
-
fig = px.bar(filtered_data, x='Crop_Year', y='Production', title='Year vs Production Count (2014-2023)',
|
176 |
-
labels={'Crop_Year': 'Year', 'Production': 'Production Count'})
|
177 |
-
fig.update_traces(marker_color='darkblue')
|
178 |
-
return fig
|
179 |
-
|
180 |
-
if __name__ == '__main__':
|
181 |
-
app.run(
|
|
|
1 |
+
from flask import Flask, render_template, request, jsonify
|
2 |
+
import pandas as pd
|
3 |
+
import plotly.express as px
|
4 |
+
import plotly.graph_objects as go
|
5 |
+
import plotly.io as pio
|
6 |
+
import joblib
|
7 |
+
import numpy as np
|
8 |
+
|
9 |
+
app = Flask(__name__)
|
10 |
+
|
11 |
+
url='https://drive.google.com/file/d/1_vd4HISZB2h2--CiXKezeWDXHHo2fY23/view?usp=sharing'
|
12 |
+
df = pd.read_csv('https://drive.usercontent.google.com/download?id={}&export=download&authuser=0&confirm=t'.format(url.split('/')[-2]))
|
13 |
+
|
14 |
+
for column in ['State', 'District', 'Crop', 'Season']:
|
15 |
+
df[column] = df[column].str.strip()
|
16 |
+
|
17 |
+
# Load the model for predictions
|
18 |
+
model_filename = 'lgb_model_cropforecastinghyperparamters__33333.pkl'
|
19 |
+
model = joblib.load(model_filename)
|
20 |
+
|
21 |
+
# Use a 2% sample for faster processing
|
22 |
+
sampled_df = df.sample(frac=0.02, random_state=42)
|
23 |
+
|
24 |
+
@app.route('/')
|
25 |
+
def index():
|
26 |
+
states = sampled_df['State'].unique()
|
27 |
+
crops = sampled_df['Crop'].unique()
|
28 |
+
seasons = sampled_df['Season'].unique()
|
29 |
+
return render_template('index.html', states=states, crops=crops, seasons=seasons)
|
30 |
+
|
31 |
+
@app.route('/filter_districts', methods=['POST'])
|
32 |
+
def filter_districts():
|
33 |
+
state = request.form['state']
|
34 |
+
districts = sampled_df[sampled_df['State'] == state]['District'].unique()
|
35 |
+
return jsonify({'districts': list(districts)})
|
36 |
+
|
37 |
+
@app.route('/predict', methods=['POST'])
|
38 |
+
def predict():
|
39 |
+
state = request.form['state']
|
40 |
+
district = request.form['district']
|
41 |
+
crop_year = int(request.form['crop_year'])
|
42 |
+
season = request.form['season']
|
43 |
+
crop = request.form['crop']
|
44 |
+
area = float(request.form['area'])
|
45 |
+
|
46 |
+
# Prepare input for prediction
|
47 |
+
input_data = pd.DataFrame({
|
48 |
+
'State': [state],
|
49 |
+
'District': [district],
|
50 |
+
'Crop_Year': [crop_year],
|
51 |
+
'Season': [season],
|
52 |
+
'Crop': [crop],
|
53 |
+
'Area': [area]
|
54 |
+
})
|
55 |
+
|
56 |
+
# Ensure consistent categories with the original DataFrame
|
57 |
+
input_data['State'] = input_data['State'].astype(pd.CategoricalDtype(categories=df['State'].unique()))
|
58 |
+
input_data['District'] = input_data['District'].astype(pd.CategoricalDtype(categories=df['District'].unique()))
|
59 |
+
input_data['Season'] = input_data['Season'].astype(pd.CategoricalDtype(categories=df['Season'].unique()))
|
60 |
+
input_data['Crop'] = input_data['Crop'].astype(pd.CategoricalDtype(categories=df['Crop'].unique()))
|
61 |
+
|
62 |
+
# Make prediction
|
63 |
+
prediction = model.predict(input_data)[0]
|
64 |
+
prediction_tons = max(0, round(prediction, 2)) # Ensure prediction is non-negative
|
65 |
+
|
66 |
+
# Calculate production/area ratio
|
67 |
+
nearest_area = find_nearest_area(state, district)
|
68 |
+
production_ratio = round((prediction_tons / nearest_area), 2)
|
69 |
+
ratio_category = categorize_production_ratio(production_ratio)
|
70 |
+
|
71 |
+
# Generate updated graphs based on the selected state and district
|
72 |
+
pie_chart = generate_pie_chart(state, district, crop)
|
73 |
+
area_vs_production = generate_area_vs_production(state, district)
|
74 |
+
season_vs_production = generate_season_vs_production(state, district)
|
75 |
+
top_states_by_production = generate_top_states_plot()
|
76 |
+
yearly_violin_plot = generate_yearly_violin_plot()
|
77 |
+
crop_year_vs_production = generate_crop_year_vs_production(state, district)
|
78 |
+
|
79 |
+
# Create gauge chart for the production ratio
|
80 |
+
gauge_chart = generate_gauge_chart(production_ratio, ratio_category)
|
81 |
+
|
82 |
+
# Hardcoded suggestions based on production ratio
|
83 |
+
suggestions = generate_suggestions(ratio_category, crop, district)
|
84 |
+
|
85 |
+
return render_template('output.html',
|
86 |
+
prediction=prediction_tons,
|
87 |
+
ratio=production_ratio,
|
88 |
+
pie_chart_html=pio.to_html(pie_chart, full_html=False),
|
89 |
+
season_vs_production_html=pio.to_html(season_vs_production, full_html=False),
|
90 |
+
area_vs_production_html=pio.to_html(area_vs_production, full_html=False),
|
91 |
+
top_states_html=pio.to_html(top_states_by_production, full_html=False),
|
92 |
+
yearly_violin_plot_html=pio.to_html(yearly_violin_plot, full_html=False),
|
93 |
+
crop_year_vs_production_html=pio.to_html(crop_year_vs_production, full_html=False),
|
94 |
+
gauge_chart_html=pio.to_html(gauge_chart, full_html=False),
|
95 |
+
suggestions=suggestions)
|
96 |
+
|
97 |
+
|
98 |
+
def find_nearest_area(state, district):
|
99 |
+
# Calculate the nearest similar area for the district using average
|
100 |
+
district_data = sampled_df[(sampled_df['State'] == state) & (sampled_df['District'] == district)]
|
101 |
+
return district_data['Area'].mean()
|
102 |
+
|
103 |
+
def categorize_production_ratio(ratio):
|
104 |
+
if ratio <= 2:
|
105 |
+
return 'Very Low'
|
106 |
+
elif ratio <= 4:
|
107 |
+
return 'Low'
|
108 |
+
elif ratio <= 6:
|
109 |
+
return 'Normal'
|
110 |
+
elif ratio <= 8:
|
111 |
+
return 'High'
|
112 |
+
else:
|
113 |
+
return 'Very High'
|
114 |
+
|
115 |
+
def generate_suggestions(category, crop, district):
|
116 |
+
suggestions = {
|
117 |
+
'Very Low': f"Increase soil nutrients and irrigation efficiency. Consider crop rotation strategies. {crop} is not suitable for {district} based on the given conditions and season. Try advanced farming methods or consider growing alternative crops that are better suited to this region.",
|
118 |
+
'Low': f"Optimize seed selection and planting techniques. {crop} is somewhat suitable for {district}, but production may be low. Monitor soil moisture regularly and apply precise farming techniques. Current strategies may need improvement for better yields.",
|
119 |
+
'Normal': f"Maintain current practices but focus on improving pest control and irrigation. {crop} is generally performing well in {district}. Production and profit depend heavily on farming practices and weather conditions, but there is potential for increased revenue.",
|
120 |
+
'High': f"Consider diversifying crops or expanding production. Explore more efficient harvesting methods to optimize yield and profitability. {crop} thrives in {district}, and with better mechanization or workforce management, you can further boost production and income potential.",
|
121 |
+
'Very High': f"{crop} is performing exceptionally well in {district}. Explore export opportunities to maximize profitability. Optimize production processes to sustain high yields while minimizing additional inputs. Consider expanding into new markets, and explore ways to reduce production costs, such as through precision farming or automation."
|
122 |
+
}
|
123 |
+
return suggestions.get(category, "No suggestions available.")
|
124 |
+
|
125 |
+
|
126 |
+
def generate_gauge_chart(ratio, category):
|
127 |
+
colors = ["#ff0000", "#ff6666", "#ffa500", "#ffff00", "#32cd32"]
|
128 |
+
fig = go.Figure(go.Indicator(
|
129 |
+
mode="gauge+number+delta",
|
130 |
+
value=ratio,
|
131 |
+
title={'text': "Production Ratio"},
|
132 |
+
delta={'reference': 5},
|
133 |
+
gauge={'axis': {'range': [None, 10]},
|
134 |
+
'bar': {'color': "darkblue"},
|
135 |
+
'steps': [{'range': [0, 2], 'color': colors[0]},
|
136 |
+
{'range': [2, 4], 'color': colors[1]},
|
137 |
+
{'range': [4, 6], 'color': colors[2]},
|
138 |
+
{'range': [6, 8], 'color': colors[3]},
|
139 |
+
{'range': [8, 10], 'color': colors[4]}]}))
|
140 |
+
return fig
|
141 |
+
|
142 |
+
def generate_pie_chart(state, district, crop):
|
143 |
+
filtered_data = sampled_df[(sampled_df['State'] == state) & (sampled_df['District'] == district)]
|
144 |
+
crop_data = filtered_data.groupby('Crop')['Production'].sum().reset_index()
|
145 |
+
crop_data['Percentage'] = (crop_data['Production'] / crop_data['Production'].sum()) * 100
|
146 |
+
crop_data = crop_data[crop_data['Percentage'] > 3]
|
147 |
+
fig = px.pie(crop_data, names='Crop', values='Production', title='Popular Crops in the Given Region')
|
148 |
+
return fig
|
149 |
+
|
150 |
+
def generate_season_vs_production(state, district):
|
151 |
+
filtered_data = sampled_df[(sampled_df['State'] == state) & (sampled_df['District'] == district)]
|
152 |
+
fig = px.bar(filtered_data, x='Season', y='Production', title='Season vs Production (Sum for All Crops)')
|
153 |
+
fig.update_traces(marker_color='darkblue')
|
154 |
+
return fig
|
155 |
+
|
156 |
+
def generate_area_vs_production(state, district):
|
157 |
+
filtered_data = sampled_df[(sampled_df['State'] == state) & (sampled_df['District'] == district)]
|
158 |
+
fig = px.density_heatmap(filtered_data, x='Area', y='Production', title='Area vs Production (Hexbin Plot)',
|
159 |
+
range_x=[0, 10000], nbinsx=5)
|
160 |
+
return fig
|
161 |
+
|
162 |
+
def generate_top_states_plot():
|
163 |
+
state_data = sampled_df.groupby('State')['Production'].sum().reset_index()
|
164 |
+
top_states = state_data.nlargest(10, 'Production')
|
165 |
+
fig = px.bar(top_states, x='State', y='Production', title='Top 10 States by Production (Overall)')
|
166 |
+
return fig
|
167 |
+
|
168 |
+
def generate_yearly_violin_plot():
|
169 |
+
filtered_data = sampled_df[sampled_df['Crop_Year'] >= 2014]
|
170 |
+
fig = px.violin(filtered_data, x='Crop_Year', y='Production', title='Violin Plot: Overall Production (2014-2023)')
|
171 |
+
return fig
|
172 |
+
|
173 |
+
def generate_crop_year_vs_production(state, district):
|
174 |
+
filtered_data = sampled_df[sampled_df['Crop_Year'] >= 2014]
|
175 |
+
fig = px.bar(filtered_data, x='Crop_Year', y='Production', title='Year vs Production Count (2014-2023)',
|
176 |
+
labels={'Crop_Year': 'Year', 'Production': 'Production Count'})
|
177 |
+
fig.update_traces(marker_color='darkblue')
|
178 |
+
return fig
|
179 |
+
|
180 |
+
if __name__ == '__main__':
|
181 |
+
app.run(port=7860,host='0.0.0.0')
|