File size: 6,186 Bytes
7273765 115003c 7273765 115003c f48c224 7273765 115003c c33d6cc 7273765 f48c224 dec834f 7273765 115003c 7273765 115003c c33d6cc 7273765 c33d6cc 7273765 115003c 7273765 115003c 7273765 c33d6cc 7273765 8398c29 edda389 7273765 c33d6cc 7273765 8398c29 a6c3a42 3d65c8f 7273765 c33d6cc 7273765 8398c29 3d65c8f 7273765 115003c 7273765 c33d6cc 7273765 3d65c8f 7273765 fa380ad c33d6cc 3d65c8f fa380ad c33d6cc fa380ad 3d65c8f fa380ad c33d6cc 115003c c33d6cc 115003c fa380ad c33d6cc 7273765 3d65c8f 7273765 115003c 3d65c8f 115003c 7273765 115003c c33d6cc 7273765 3d65c8f 7273765 8398c29 3d65c8f 8398c29 3d65c8f 7273765 3d65c8f 115003c 7273765 3d65c8f 7273765 3d65c8f 7273765 3d65c8f 7273765 115003c 7273765 115003c 7273765 115003c dbaae56 115003c c33d6cc 7273765 c33d6cc 115003c |
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 |
import faicons as fa
import plotly.express as px
import pandas as pd
# بارگذاری دادهها
from shared import app_dir, tips # فرض بر این است که tips از قبل DataFrame است
from shinywidgets import render_plotly
from shiny import reactive, render
from shiny.express import input, ui
# تبدیل احساس به عدد (تحلیل احساسات)
tips["tip"] = tips["احساس"].map({"مثبت": 1, "خنثی": 0, "منفی": -1})
# تعیین بازه سنی
bill_rng = (min(tips.سن), max(tips.سن))
# صفحه و سایدبار
ui.page_opts(title="تحلیل احساسات کاربران", fillable=True)
with ui.sidebar(open="desktop"):
ui.input_slider(
"سن",
"رنج سنی",
min=bill_rng[0],
max=bill_rng[1],
value=bill_rng,
pre="سال"
)
ui.input_checkbox_group(
"تاریخ",
"شبکه اجتماعی",
tips["شبکه اجتماعی"].unique().tolist(),
selected=tips["شبکه اجتماعی"].unique().tolist(),
inline=True,
)
ui.input_action_button("reset", "بازنشانی فیلتر")
# آیکونها
ICONS = {
"user": fa.icon_svg("user", "regular"),
"wallet": fa.icon_svg("wallet"),
"currency-dollar": fa.icon_svg("dollar-sign"),
"ellipsis": fa.icon_svg("ellipsis"),
}
# باکسهای آماری
with ui.layout_columns(fill=False):
with ui.value_box(showcase=ICONS["user"]):
"تعداد کاربران"
@render.express
def total_tippers():
data = tips_data()
ui.h3(f"تعداد کاربران: {data.shape[0]}")
with ui.value_box(showcase=ICONS["wallet"]):
"میانگین احساس"
@render.express
def average_tip():
data = tips_data()
if data.shape[0] > 0:
ui.h3(f"میانگین احساس مثبت یا منفی: {data['tip'].mean():.2f}")
else:
ui.h3("دادهای برای محاسبه میانگین وجود ندارد.")
with ui.value_box(showcase=ICONS["currency-dollar"]):
"میانگین سن"
@render.express
def average_bill():
data = tips_data()
if data.shape[0] > 0:
ui.h3(f"میانگین سن: {data['سن'].mean():.1f} سال")
else:
ui.h3("دادهای برای محاسبه میانگین سن وجود ندارد.")
# نمودار و جدول
with ui.layout_columns(col_widths=[6, 6, 12]):
with ui.card(full_screen=True):
ui.card_header("جدول دادهها")
# رندر کردن دادهها در قالب جدول
@render.data_frame
def table():
return tips_data()
# رندر کردن نمودار پراکندگی
@render_plotly
def scatterplot():
data = tips_data()
if data.shape[0] == 0:
return {} # بازگرداندن دادههای خالی در صورت عدم وجود داده
return px.scatter(
data,
x="سن",
y="tip",
color="جنسیت",
trendline="lowess",
labels={"tip": "امتیاز احساس", "سن": "سن"},
title="رابطه سن با احساس"
)
with ui.card(full_screen=True):
# عنوان برای تحلیل پراکندگی احساس
with ui.card_header(class_="d-flex justify-content-between align-items-center"):
"تحلیل پراکندگی احساس"
# ایجاد یک Popover برای انتخاب متغیر گروهبندی
with ui.popover(title="گروهبندی بر اساس متغیر"):
ICONS["ellipsis"]
ui.input_radio_buttons(
"tip_perc_y",
"گروهبندی بر اساس:",
["جنسیت", "تأثیر", "سطح تأثیر", "موضوع"],
selected="جنسیت",
inline=True,
)
# رندر کردن نمودار ridgeplot
@render_plotly
def tip_perc():
from ridgeplot import ridgeplot
dat = tips_data()
if dat.shape[0] == 0:
return {} # بازگرداندن دادههای خالی در صورت عدم وجود داده
dat["percent"] = dat["tip"] # استفاده از 'tip' به عنوان درصد احساس
yvar = input.tip_perc_y() # دریافت انتخاب از کاربر
uvals = dat[yvar].unique() # استخراج مقادیر یکتای متغیر انتخابی
# ایجاد نمونهها برای رسم نمودار ridgeplot
samples = [[dat.percent[dat[yvar] == val]] for val in uvals]
# ایجاد نمودار ridgeplot
plt = ridgeplot(
samples=samples,
labels=uvals,
bandwidth=0.01,
colorscale="viridis",
colormode="row-index",
)
# تنظیمات نهایی برای نمودار
plt.update_layout(
legend=dict(
orientation="h", yanchor="bottom", y=1.02, xanchor="center", x=0.5
)
)
return plt # بازگشت نمودار
# اعمال CSS
ui.include_css(app_dir / "styles.css")
# --------------------------------------------------------
# واکنشها
# --------------------------------------------------------
@reactive.calc
def tips_data():
سنی = input.سن()
تاریخ_انتخابی = input.تاریخ()
idx1 = tips["سن"].between(سنی[0], سنی[1])
idx2 = tips["شبکه اجتماعی"].isin(تاریخ_انتخابی)
return tips[idx1 & idx2]
@reactive.effect
@reactive.event(input.reset)
def _():
ui.update_slider("سن", value=bill_rng)
ui.update_checkbox_group("تاریخ", selected=tips["شبکه اجتماعی"].unique().tolist()) |