591Analyzer / app.py
54justin's picture
Create app.py
c22b7de verified
# 由 Copilot 生成
# 591租屋分析器 - 簡化版本(避免套件依賴問題)
import gradio as gr
import pandas as pd
import numpy as np
from datetime import datetime
import json
def generate_rental_data(sample_size):
"""生成高雄市鼓山區租屋模擬資料"""
np.random.seed(42)
# 鼓山區常見地址
addresses = [
'高雄市鼓山區美術館路', '高雄市鼓山區博愛路', '高雄市鼓山區明誠路',
'高雄市鼓山區文信路', '高雄市鼓山區裕誠路', '高雄市鼓山區華榮路',
'高雄市鼓山區龍德路', '高雄市鼓山區鼓山路', '高雄市鼓山區九如路',
'高雄市鼓山區綠川街', '高雄市鼓山區美術東路', '高雄市鼓山區青海路'
]
# 房屋特色關鍵字
features = [
'近捷運', '電梯大樓', '採光佳', '通風良好', '停車位', '管理完善',
'生活機能佳', '近美術館', '學區', '安靜社區', '新裝潢', '家具家電'
]
data = []
for i in range(int(sample_size)):
# 基本資料
area = np.random.normal(32, 6) # 平均32坪,標準差6
area = max(25, min(45, area)) # 限制在25-45坪之間
# 租金計算(基於坪數和隨機因子)
base_price = area * np.random.normal(800, 100) # 每坪約800元
location_factor = np.random.uniform(0.8, 1.3) # 地段因子
price = int(base_price * location_factor)
price = max(18000, min(45000, price)) # 限制在合理範圍
# 選擇地址和特色
address = np.random.choice(addresses) + f"{i+1}號"
selected_features = np.random.choice(features,
size=np.random.randint(2, 5),
replace=False)
data.append({
'title': f'鼓山區2房電梯大樓-{i+1}',
'price': price,
'area': round(area, 1),
'price_per_ping': round(price / area, 0),
'address': address,
'features': ', '.join(selected_features),
'type': '整層住家',
'layout': '2房1廳1衛',
'building_type': '電梯大樓'
})
return pd.DataFrame(data)
def analyze_rental_data(sample_size, analysis_type):
"""執行租屋資料分析"""
try:
# 生成資料
df = generate_rental_data(sample_size)
if df.empty:
return "❌ 無法生成資料", None, None, pd.DataFrame()
# 基本統計
stats = {
'total_count': len(df),
'avg_price': df['price'].mean(),
'median_price': df['price'].median(),
'std_price': df['price'].std(),
'min_price': df['price'].min(),
'max_price': df['price'].max(),
'avg_area': df['area'].mean(),
'avg_price_per_ping': df['price_per_ping'].mean()
}
# 生成分析報告
report = f"""
# 🏠 高雄市鼓山區租屋市場分析報告
**分析時間**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
**資料來源**: 591租屋網模擬資料
**分析條件**: 2房整層電梯大樓
## 📊 市場概況
### 基本統計
- **總物件數**: {stats['total_count']}
- **平均租金**: NT$ {stats['avg_price']:,.0f} 元/月
- **租金中位數**: NT$ {stats['median_price']:,.0f} 元/月
- **租金標準差**: NT$ {stats['std_price']:,.0f}
- **租金區間**: NT$ {stats['min_price']:,.0f} ~ {stats['max_price']:,.0f}
### 坪數分析
- **平均坪數**: {stats['avg_area']:.1f}
- **平均每坪租金**: NT$ {stats['avg_price_per_ping']:,.0f} 元/坪
### 市場洞察
"""
# 根據分析類型添加額外洞察
if stats['avg_price'] > stats['median_price']:
report += "- 租金分布偏右,存在高價物件拉高平均值\n"
if stats['avg_price_per_ping'] > 900:
report += "- 每坪租金偏高,顯示該區域生活機能佳\n"
elif stats['avg_price_per_ping'] < 700:
report += "- 每坪租金相對親民,適合小資族群\n"
report += f"\n**由 GitHub Copilot 生成** ✨"
# 生成統計表格
price_stats, price_dist = create_price_distribution_chart(df, analysis_type)
area_stats, price_per_ping_stats = create_area_analysis_chart(df, analysis_type)
# 準備資料表格
display_df = df[['title', 'price', 'area', 'price_per_ping', 'address', 'features']].copy()
display_df.columns = ['物件名稱', '租金(元)', '坪數', '每坪租金', '地址', '特色']
return report, price_stats, area_stats, price_dist, price_per_ping_stats, display_df
except Exception as e:
error_msg = f"❌ 分析過程發生錯誤: {str(e)}\n\n請稍後再試或聯繫技術支援。"
empty_df = pd.DataFrame()
return error_msg, empty_df, empty_df, empty_df, empty_df, empty_df
def create_price_distribution_chart(df, analysis_type):
"""創建租金分布統計表格"""
# 創建租金分布統計
price_stats = {
'統計項目': ['最低租金', '最高租金', '平均租金', '中位數租金', '標準差'],
'數值 (元)': [
f"{df['price'].min():,}",
f"{df['price'].max():,}",
f"{df['price'].mean():.0f}",
f"{df['price'].median():.0f}",
f"{df['price'].std():.0f}"
]
}
# 租金區間分布
df_temp = df.copy()
df_temp['price_range'] = pd.cut(df_temp['price'],
bins=[0, 20000, 25000, 30000, 35000, float('inf')],
labels=['<2萬', '2-2.5萬', '2.5-3萬', '3-3.5萬', '>3.5萬'])
range_counts = df_temp['price_range'].value_counts().sort_index()
distribution_data = {
'租金區間': range_counts.index.tolist(),
'物件數量': range_counts.values.tolist(),
'占比 (%)': [f"{(count/len(df)*100):.1f}%" for count in range_counts.values]
}
return pd.DataFrame(price_stats), pd.DataFrame(distribution_data)
def create_area_analysis_chart(df, analysis_type):
"""創建坪數分析統計表格"""
# 坪數統計
area_stats = {
'統計項目': ['最小坪數', '最大坪數', '平均坪數', '中位數坪數'],
'數值 (坪)': [
f"{df['area'].min():.1f}",
f"{df['area'].max():.1f}",
f"{df['area'].mean():.1f}",
f"{df['area'].median():.1f}"
]
}
# 每坪租金統計
price_per_ping_stats = {
'統計項目': ['最低每坪租金', '最高每坪租金', '平均每坪租金', '中位數每坪租金'],
'數值 (元/坪)': [
f"{df['price_per_ping'].min():.0f}",
f"{df['price_per_ping'].max():.0f}",
f"{df['price_per_ping'].mean():.0f}",
f"{df['price_per_ping'].median():.0f}"
]
}
return pd.DataFrame(area_stats), pd.DataFrame(price_per_ping_stats)
# 創建 Gradio 介面
with gr.Blocks(title="🏠 591租屋分析器", theme=gr.themes.Soft()) as demo:
gr.Markdown("""
# 🏠 591租屋分析器 - 高雄市鼓山區
專門分析高雄市鼓山區2房整層電梯大樓租屋市場,提供詳細的統計分析和視覺化圖表。
**目標條件**:高雄市鼓山區 | 2房 | 整層住家 | 電梯大樓
""")
with gr.Row():
with gr.Column(scale=1):
sample_size = gr.Slider(
minimum=20, maximum=200, value=80, step=10,
label="📊 分析樣本數",
info="選擇要生成的租屋物件數量"
)
analysis_type = gr.Radio(
choices=["基本分析", "進階分析", "詳細分析"],
value="基本分析",
label="🔍 分析類型",
info="選擇分析的詳細程度"
)
analyze_btn = gr.Button("🚀 開始分析", variant="primary", size="lg")
with gr.Column(scale=2):
with gr.Tab("📋 分析報告"):
report_output = gr.Markdown(label="分析報告")
with gr.Tab("📊 統計分析"):
with gr.Row():
with gr.Column():
price_stats_output = gr.Dataframe(label="租金統計")
price_dist_output = gr.Dataframe(label="租金區間分布")
with gr.Column():
area_stats_output = gr.Dataframe(label="坪數統計")
price_per_ping_output = gr.Dataframe(label="每坪租金統計")
with gr.Tab("📁 詳細資料"):
data_output = gr.Dataframe(
label="租屋物件詳細資料",
interactive=True,
wrap=True
)
# 設定按鈕事件
analyze_btn.click(
fn=analyze_rental_data,
inputs=[sample_size, analysis_type],
outputs=[report_output, price_stats_output, area_stats_output,
price_dist_output, price_per_ping_output, data_output]
)
gr.Markdown("""
---
**📍 分析範圍**: 高雄市鼓山區 (美術館、愛河、駁二藝術特區周邊)
**🏠 物件類型**: 2房1廳1衛、整層住家、電梯大樓
**📊 資料說明**: 使用模擬資料展示分析功能,實際部署可串接真實API
*由 GitHub Copilot 生成* ✨
""")
if __name__ == "__main__":
demo.launch()