File size: 6,336 Bytes
e522499
cdf0803
 
 
 
01ac828
cdf0803
15c01f8
cdf0803
 
1ce52fb
 
cdf0803
 
 
1ce52fb
 
cdf0803
15c01f8
cdf0803
 
 
01ac828
cdf0803
01ac828
 
 
cdf0803
01ac828
 
 
 
 
cdf0803
 
01ac828
 
 
 
 
 
 
 
cdf0803
15c01f8
cdf0803
 
 
 
 
 
 
 
 
 
 
 
 
 
15c01f8
cdf0803
 
 
 
 
 
 
 
 
 
 
 
15c01f8
cdf0803
15c01f8
cdf0803
 
 
15c01f8
cdf0803
 
15c01f8
cdf0803
 
01ac828
15c01f8
cdf0803
 
 
 
a1d5478
cdf0803
15c01f8
cdf0803
 
 
 
 
 
 
 
 
 
 
 
 
15c01f8
cdf0803
 
15c01f8
 
cdf0803
 
 
 
 
 
 
15c01f8
 
cdf0803
15c01f8
cdf0803
 
 
 
 
01ac828
 
cdf0803
 
 
 
 
01ac828
15c01f8
cdf0803
 
 
 
 
15c01f8
cdf0803
 
 
 
 
01ac828
 
cdf0803
 
 
15c01f8
cdf0803
 
 
15c01f8
cdf0803
 
15c01f8
cdf0803
e522499
 
cdf0803
 
 
 
 
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
import streamlit as st
import pandas as pd
import numpy as np

# 设置页面布局为宽屏模式,并设置页面标题
st.set_page_config(layout="wide", page_title="影城排片效率分析")


def clean_movie_title(title):
    """
    清理并规范化电影标题。
    根据用户最新指示:只保留字符串中第一个空格之前的部分。
    """
    if not isinstance(title, str):
        return title
    # 将标题按第一个空格分割,并只取第一部分
    return title.split(' ', 1)[0]


def style_efficiency(row):
    """
    根据效率值高亮特定行。
    高于 1.5 的淡绿色,低于 0.5 的淡红色。
    """
    # 定义颜色
    green = 'background-color: #E6F5E6;'  # 淡绿色
    red = 'background-color: #FFE5E5;'  # 淡红色
    default = ''

    # 初始化样式列表,长度与行内元素数量一致
    styles = [default] * len(row)

    # 获取效率值
    seat_efficiency = row.get('座次效率', 0)
    session_efficiency = row.get('场次效率', 0)

    # 判断并应用样式
    if seat_efficiency > 1.5 or session_efficiency > 1.5:
        styles = [green] * len(row)
    elif seat_efficiency < 0.5 or session_efficiency < 0.5:
        styles = [red] * len(row)

    return styles


def process_and_analyze_data(df):
    """
    核心数据处理与分析函数。
    """
    if df.empty:
        return pd.DataFrame()

    analysis_df = df.groupby('影片名称_清理后').agg(
        座位数=('座位数', 'sum'),
        场次=('影片名称_清理后', 'size'),
        票房=('总收入', 'sum'),
        人次=('总人次', 'sum')
    ).reset_index()
    analysis_df.rename(columns={'影片名称_清理后': '影片'}, inplace=True)

    analysis_df = analysis_df.sort_values(by='票房', ascending=False).reset_index(drop=True)

    total_seats = analysis_df['座位数'].sum()
    total_sessions = analysis_df['场次'].sum()
    total_revenue = analysis_df['票房'].sum()

    analysis_df['均价'] = np.divide(analysis_df['票房'], analysis_df['人次']).fillna(0)
    analysis_df['座次比'] = np.divide(analysis_df['座位数'], total_seats).fillna(0)
    analysis_df['场次比'] = np.divide(analysis_df['场次'], total_sessions).fillna(0)
    analysis_df['票房比'] = np.divide(analysis_df['票房'], total_revenue).fillna(0)
    analysis_df['座次效率'] = np.divide(analysis_df['票房比'], analysis_df['座次比']).fillna(0)
    analysis_df['场次效率'] = np.divide(analysis_df['票房比'], analysis_df['场次比']).fillna(0)

    final_columns = [
        '影片', '座位数', '场次', '票房', '人次', '均价',
        '座次比', '场次比', '票房比', '座次效率', '场次效率'
    ]
    analysis_df = analysis_df[final_columns]

    return analysis_df


# --- Streamlit 用户界面 ---

st.title('影城排片效率分析工具')
st.write("上传 `影片映出日累计报表.xlsx` 文件。")

uploaded_file = st.file_uploader("请在此处上传 Excel 文件", type=['xlsx', 'xls', 'csv'])

if uploaded_file is not None:
    try:
        df = pd.read_excel(uploaded_file, skiprows=3, header=None)

        df.rename(columns={
            0: '影片名称', 2: '放映时间', 5: '总人次', 6: '总收入', 7: '座位数'
        }, inplace=True)

        required_cols = ['影片名称', '放映时间', '座位数', '总收入', '总人次']
        df = df[required_cols]
        df.dropna(subset=['影片名称', '放映时间'], inplace=True)

        for col in ['座位数', '总收入', '总人次']:
            df[col] = pd.to_numeric(df[col], errors='coerce').fillna(0)

        df['放映时间'] = pd.to_datetime(df['放映时间'], format='%H:%M:%S', errors='coerce').dt.time
        df.dropna(subset=['放映时间'], inplace=True)

        df['影片名称_清理后'] = df['影片名称'].apply(clean_movie_title)

        st.toast("文件上传成功,数据已按规则处理!", icon="🎉")

        format_config = {
            '座位数': '{:,.0f}', '场次': '{:,.0f}', '人次': '{:,.0f}',
            '票房': '{:,.2f}', '均价': '{:.2f}', '座次比': '{:.2%}', '场次比': '{:.2%}',
            '票房比': '{:.2%}', '座次效率': '{:.2f}', '场次效率': '{:.2f}',
        }

        # --- 1. 全天数据分析 ---
        st.header("全天排片效率分析")

        full_day_analysis = process_and_analyze_data(df.copy())

        if not full_day_analysis.empty:
            table_height = (len(full_day_analysis) + 1) * 35 + 3
            st.dataframe(
                full_day_analysis.style.format(format_config).apply(style_efficiency, axis=1).hide(axis="index"),
                height=table_height,
                use_container_width=True,
                hide_index=True
            )
        else:
            st.warning("全天数据不足,无法生成分析报告。")

        # --- 2. 黄金时段数据分析 ---
        st.header("黄金时段排片效率分析 (14:00-21:00)")

        start_time = pd.to_datetime('14:00:00').time()
        end_time = pd.to_datetime('21:00:00').time()
        prime_time_df = df[df['放映时间'].between(start_time, end_time)]

        prime_time_analysis = process_and_analyze_data(prime_time_df.copy())

        if not prime_time_analysis.empty:
            table_height_prime = (len(prime_time_analysis) + 1) * 35 + 3
            st.dataframe(
                prime_time_analysis.style.format(format_config).apply(style_efficiency, axis=1).hide(axis="index"),
                height=table_height_prime,
                use_container_width=True,
                hide_index = True
            )
        else:
            st.warning("黄金时段内没有有效场次数据,无法生成分析报告。")

        # --- 3. 一键复制影片列表 ---
        if not full_day_analysis.empty:
            st.header("复制当日影片列表")

            movie_titles = full_day_analysis['影片'].tolist()
            formatted_titles = ''.join([f'《{title}》' for title in movie_titles])

            st.code(formatted_titles, language='text')

    except Exception as e:
        st.error(f"处理文件时出错: {e}")
        st.warning("请确保上传的文件是'影片映出日累计报表.xlsx',并且格式正确。")

else:
    st.info("请上传文件以开始分析。")