数据:链接:https://pan.baidu.com/s/1AcyhgmkWqdy-K6gvRZaFsg
提取码:1234
用Pandas揭秘美国选民的总统喜好数据分析(数据清洗+可视化分析)
一.确定问题:
分析美国选民对总统的喜好.什么喜好?->具体就是反向分析,通过分析选民投票各种分类结果得到的投票排行,分析各种选民对什么总统更有好感,更偏向于谁
二.分解问题
由一我们可以将问题分为对各种分类结果的投票排行分析,各种人对美国总统的偏向程度,比如分析投票人的党派,由党派投票排行+对应候选总统所属党派判断从党派投票上谁更有优势,当然不排除选民是A党派,但他选了B党的候选人,但是这种情况毕竟属于选举的少数情况,因为总统所在党派始终会更有话语权.并且一些关键性法案也会更偏向于总统所在党派.
三.数据分析与可视化处理:
1.获取数据:
进行数据处理前,我们需要知道我们最终想要的数据是什么样的,因为我们是想分析候选人与捐赠人之间的关系,所以我们想要一张数据表中有捐赠人与候选人一一对应的关系,所以需要将目前的三张数据表进行一一关联,汇总到需要的数据。
- 将委员会和候选人一一对应,通过CAND_ID关联两个表
- 将候选人和捐赠人一一对应,通过CMTE_ID关联两个表
具体操作如下:
#由于候选人和委员会的联系表中无候选人姓名,只有候选人ID(CAND_ID),所以需要通过CAND_ID从候选人表中获取到候选人姓名,最终得到候选人与委员会联系表ccl。
# 导入相关处理包
import pandas as pd
# 读取候选人信息,由于原始数据没有表头,需要添加表头
#关联weball20.txt和ccl.txt
candidates = pd.read_csv("weball20.txt", sep = '|',names=['CAND_ID','CAND_NAME','CAND_ICI','PTY_CD','CAND_PTY_AFFILIATION','TTL_RECEIPTS',
'TRANS_FROM_AUTH','TTL_DISB','TRANS_TO_AUTH','COH_BOP','COH_COP','CAND_CONTRIB',
'CAND_LOANS','OTHER_LOANS','CAND_LOAN_REPAY','OTHER_LOAN_REPAY','DEBTS_OWED_BY',
'TTL_INDIV_CONTRIB','CAND_OFFICE_ST','CAND_OFFICE_DISTRICT','SPEC_ELECTION','PRIM_ELECTION','RUN_ELECTION'
,'GEN_ELECTION','GEN_ELECTION_PRECENT','OTHER_POL_CMTE_CONTRIB','POL_PTY_CONTRIB',
'CVG_END_DT','INDIV_REFUNDS','CMTE_REFUNDS'])
# 读取候选人和委员会的联系信息
df_data = pd.read_csv("ccl.txt", sep = '|',names=['CAND_ID','CAND_ELECTION_YR','FEC_ELECTION_YR','CMTE_ID','CMTE_TP','CMTE_DSGN','LINKAGE_ID'])
# 关联两个表数据
df_data1 = pd.merge(df_data1,candidates)
# 提取出所需要的列
df_data1 = pd.DataFrame(df_data1, columns=[ 'CMTE_ID','CAND_ID', 'CAND_NAME','CAND_PTY_AFFILIATION'])
#关联上面合并好的表ccl和表itcont_2020_20200722_20200820.txt
# 读取个人捐赠数据,由于原始数据没有表头,需要添加表头
df_data2 = pd.read_csv('itcont_2020_20200722_20200820.txt', sep='|',names=['CMTE_ID','AMNDT_IND','RPT_TP','TRANSACTION_PGI',
'IMAGE_NUM','TRANSACTION_TP','ENTITY_TP','NAME','CITY',
'STATE','ZIP_CODE','EMPLOYER','OCCUPATION','TRANSACTION_DT',
'TRANSACTION_AMT','OTHER_ID','TRAN_ID','FILE_NUM','MEMO_CD',
'MEMO_TEXT','SUB_ID'])
# 将候选人与委员会关系表ccl和个人捐赠数据表itcont合并,通过 CMTE_ID
df_data2 = pd.merge(ccl,itcont)
# 提取需要的数据列
df_data2 = pd.DataFrame(df_data2, columns=[ 'CAND_NAME','NAME', 'STATE','EMPLOYER','OCCUPATION',
'TRANSACTION_AMT', 'TRANSACTION_DT','CAND_PTY_AFFILIATION'])
字段说明:
CAND_NAME – 接受捐赠的候选人姓名
NAME – 捐赠人姓名
STATE – 捐赠人所在州
EMPLOYER – 捐赠人所在公司
OCCUPATION – 捐赠人职业
TRANSACTION_AMT – 捐赠数额(美元)
TRANSACTION_DT – 收到捐款的日期
CAND_PTY_AFFILIATION – 候选人党派
得到的数据如下:
2.数据处理
获得了可用的数据集,现在我们可以利用调用shape属性查看数据的规模,调用info函数查看数据信息,调用describe函数查看数据分布。
# 查看数据规模 多少行 多少列
df_data2.shape
# 查看整体数据信息,包括每个字段的名称、非空数量、字段的数据类型
df_data2.info()
结果如图:
由图可得数据中存在缺失值需要处理
通过分析对应列的数据我们将缺失值赋值为NOT PROVIDED(实际是根据的实际请况)如其中缺失比较多的OCCUPATION实际上就很多都是平民,没有实际的工作,所以使用NOT PROVIDED实际上比较合适,EMPLOYER为空很大概率上选民就是boss
#空值处理,统一填充 NOT PROVIDED
df_data2['STATE'].fillna('NOT PROVIDED',inplace=True)
df_data2['EMPLOYER'].fillna('NOT PROVIDED',inplace=True)
df_data2['OCCUPATION'].fillna('NOT PROVIDED',inplace=True)
# 对日期TRANSACTION_DT列进行处理,即是为了这里的修改值,也是为了之后使用sum对捐赠数求和
df_data2['TRANSACTION_DT'] = df_data2['TRANSACTION_DT'] .astype(str)
# 将日期格式改为年月日 7242020
df_data2['TRANSACTION_DT'] = [i[3:7]+i[0]+i[1:3] for i in df_data2['TRANSACTION_DT'] ]
# 查看数据前3行,判断是否是我们需要的数据
df_data2.head(3)
结果如下:
查看每一行的具体数据是怎么样的方便进行下一步操作
for i in df_data2.columns:
print(df_data2.groupby(i).size())
结果太多不做展示:
大致意思就是,大致浏览其中是否有不正常的数据,比如这次我发现数据中捐款数存在负数的情况,鉴于这是一种不科学的情况,所以我对捐款单独处理了一下,将所有为负的捐款都赋值为0
df_data2['TRANSACTION_AMT']=df_data2['TRANSACTION_AMT'].apply(lambda x:x if x>0 else 0)
3.数据可视化分析:
- 分析各个候选人top25获得的总票数-使用词云图
- 分析各个候选人获得捐款情况
- 分析各个候选人获得的总捐款top10和对拜登捐赠最多的10个职业
- 分析选民的党派
- 分析拜登在各个州获得的捐赠占比
- 分析各个州总捐款top10和对应的捐赠人数以及这几个州的人均捐赠数
- 分析过去的一个月中每天捐赠数变化
- 分析过去一个月中总捐赠额top10的州每天捐赠流入情况
- 分析过去一个月中总捐赠额top10的职业每天捐赠流入情况
- 分析总捐赠数top10的天总捐赠人数和总捐赠数变化
- 分析其中产生差错的原因
1.分析各个候选人top25获得的总票数-使用词云图
数据可视化实际上就分为得到使用数据(一般是x,y数据我一般使用df_data_x/df_data_y/data_x/data_y的形式)和实际数据代入画图
from pyecharts import options as opts
#词云图
from pyecharts.charts import WordCloud, Boxplot
#是基于人数排名的
y_NAME=df_data2.groupby('CAND_NAME').size().sort_values(ascending=False).head(25).values.tolist()
x_NAME=df_data2.groupby('CAND_NAME').size().sort_values(ascending=False).head(25).index.tolist()
data_111=list(zip(x_NAME,y_NAME))
# print(data_111)
word=(
WordCloud(init_opts=opts.InitOpts(width="1900px", height="1000px",theme=ThemeType.DARK))
.add(series_name="票选人物TOP25", data_pair=data_111, word_size_range=[20, 100],shape=SymbolType.DIAMOND)
.set_global_opts(
title_opts=opts.TitleOpts(
title="ballots_top-25", title_textstyle_opts=opts.TextStyleOpts(font_size=23)
),
tooltip_opts=opts.TooltipOpts(is_show=True),
)
)
结果如下:
从图中我们可以明显看到拜登比其他候选人在获得票数上更有优势,所以我们继续分析这些候选人总获得的捐赠数,因为我们知道美国大选不同与其他国家,大选是十分消耗资金的,所以在资金上有优势,在大选中也会更有优势
2.分析各个候选人获得捐款情况
Y_container=[]
for i in x_NAME:#前25个人的箱型数据
Y_container.append(df_data2[df_data2.CAND_NAME==i]["TRANSACTION_AMT"].values.tolist())
#单独分析其中比较突出的两个候选人,我们只关注给他们捐款的钱数,公司,还有对应捐款人的职业
print(x_NAME[1]+':')
print(df_data2[df_data2.CAND_NAME==x_NAME[1]].loc[:,['TRANSACTION_AMT','EMPLOYER','OCCUPATION']].sort_values('TRANSACTION_AMT',ascending=False).head(25))
print(df_data2[df_data2.CAND_NAME==x_NAME[1]].groupby('EMPLOYER').sum().sort_values('TRANSACTION_AMT',ascending=False).head(25))
print(x_NAME[2]+':')
print(df_data2[df_data2.CAND_NAME==x_NAME[2]].loc[:,['TRANSACTION_AMT','EMPLOYER','OCCUPATION']].sort_values('TRANSACTION_AMT',ascending=False).head(25))
print(df_data2[df_data2.CAND_NAME==x_NAME[2]].groupby('EMPLOYER').sum().sort_values('TRANSACTION_AMT',ascending=False).head(25))
box_plot = Boxplot(init_opts=opts.InitOpts(width="2400px", height="1500px",theme=ThemeType.CHALK))
box_plot = (
box_plot.add_xaxis(xaxis_data=x_NAME)
.add_yaxis(series_name="", y_axis=box_plot.prepare_data(Y_container),itemstyle_opts=opts.ItemStyleOpts(color='blue'))
.set_global_opts(
datazoom_opts=opts.DataZoomOpts(is_show=True),
title_opts=opts.TitleOpts(
pos_left="center", title="GAND_NAME_TOP25获取捐款"
),
tooltip_opts=opts.TooltipOpts(trigger="item", axis_pointer_type="shadow"),
xaxis_opts=opts.AxisOpts(
# type_="category",
boundary_gap=True,
splitarea_opts=opts.SplitAreaOpts(is_show=False),
# axislabel_opts=opts.LabelOpts(formatter="expr {value}"),
splitline_opts=opts.SplitLineOpts(is_show=False),
),
yaxis_opts=opts.AxisOpts(
# type_="value",#值轴,一般默认的是类别轴
type_='value',
name="所获捐赠",
splitarea_opts=opts.SplitAreaOpts(
is_show=True, areastyle_opts=opts.AreaStyleOpts(opacity=1)
),
),
)
.set_series_opts(tooltip_opts=opts.TooltipOpts(formatter="{b}: {c}"))
)
结果如下:
可以看到因为第2和第三的最大值很大导致整体数据分析不明显所以我们单独取出这两个数据并分析其余数据的获捐赠情况
SULLIVAN,DAN:
JACOBS,CHRISTOPHER L.:
删除异常的两个数据:
x_NAME1=x_NAME[3:].copy()
x_NAME1.insert(0,x_NAME[0])
Y_container1=Y_container[3:].copy()
Y_container1.insert(0,Y_container[0])
box_plot1 = Boxplot(init_opts=opts.InitOpts(width="1900px", height="1100px",theme=ThemeType.CHALK))
box_plot1 = (
box_plot1.add_xaxis(xaxis_data=x_NAME1)
.add_yaxis(series_name="", y_axis=box_plot1.prepare_data(Y_container1),itemstyle_opts=opts.ItemStyleOpts(color='blue'))
.set_global_opts(
datazoom_opts=opts.DataZoomOpts(is_show=True),
title_opts=opts.TitleOpts(
pos_left="center", title="GAND_NAME_TOP25获取捐款"
),
tooltip_opts=opts.TooltipOpts(trigger="item", axis_pointer_type="shadow"),
xaxis_opts=opts.AxisOpts(
# type_="category",
boundary_gap=True,
splitarea_opts=opts.SplitAreaOpts(is_show=False),
# axislabel_opts=opts.LabelOpts(formatter="expr {value}"),
splitline_opts=opts.SplitLineOpts(is_show=False),
),
yaxis_opts=opts.AxisOpts(
# type_="value",#值轴,一般默认的是类别轴
type_='value',
name="所获捐赠",
splitarea_opts=opts.SplitAreaOpts(
is_show=True, areastyle_opts=opts.AreaStyleOpts(opacity=1)
),
),
)
.set_series_opts(tooltip_opts=opts.TooltipOpts(formatter="{b}: {c}"))
)
结果如下:
可以发现拜登获得的捐款无论是后50%还是前50%都要比其他候选人小,这不禁让人失望,因为通过前面的词云图分析我们已经很看好拜登了,因为它人数占优势…!!!,或许我们找到了答案
3.分析各个候选人获得的总捐款top10和对拜登捐赠最多的10个职业
前面分析我们发现拜登在获得捐款的数据中拜登一点优势都没有了,但是我们发现拜登获得投票的/捐款的人数比较多,是否可能最后拜登是量大数小?带着疑问开始数据分析
# 前面的结果似乎耐人寻味,因为排名第一的拜登似乎最大值,平均值都没别人的大
sum_data=df_data2.groupby('CAND_NAME').sum().sort_values('TRANSACTION_AMT',ascending=False).head(10).sort_values('TRANSACTION_AMT',ascending=True)['TRANSACTION_AMT']
sum_data_y=sum_data.values.tolist()
sum_data_x=sum_data.index.tolist()
from pyecharts.charts import Bar
bar_1=(
Bar(init_opts=opts.InitOpts(width="1700px", height="1000px",theme=ThemeType.CHALK))
.add_xaxis(sum_data_x)
.add_yaxis('获得的捐赠总金额',sum_data_y,bar_width='40%')
.reversal_axis()
.set_global_opts(title_opts=opts.TitleOpts(title='获得捐赠总金额排名前10的候选人',pos_left='left'),legend_opts=opts.LegendOpts(pos_left='left',is_show=False))
)
# 分析拜登参与投票中的职业捐款组成
OCCUPATION_data=df_data2[df_data2.CAND_NAME==x_NAME[0]].groupby('OCCUPATION').sum().sort_values('TRANSACTION_AMT',ascending=False).head(10).sort_values('TRANSACTION_AMT',ascending=True)
OCCUPATION_data_y=OCCUPATION_data['TRANSACTION_AMT'].values.tolist()
OCCUPATION_data_x=OCCUPATION_data.index.tolist()
bar_2=(
Bar(init_opts=opts.InitOpts(width="1700px", height="1000px",theme=ThemeType.CHALK))
.add_xaxis(OCCUPATION_data_x)
.add_yaxis('捐赠总金额',OCCUPATION_data_y,bar_width='40%')
.reversal_axis()
.set_global_opts(title_opts=opts.TitleOpts(title='对拜登捐赠总金额排名前10的职业',pos_right='center'),legend_opts=opts.LegendOpts(pos_right='right',is_show=False))
)
from pyecharts.charts import Grid
grid_1=(
Grid(init_opts=opts.InitOpts(width='1900px',height='1000px',theme=ThemeType.CHALK))
.add(bar_1,grid_opts=opts.GridOpts(pos_right='55%'))
.add(bar_2,grid_opts=opts.GridOpts(pos_left='55%'))
)
似乎结果如我们所想,拜登凭借人多的优势其获得的捐款也多,然后我分析了对拜登捐款最多的10个职业,发现更多是来自平民捐款,这也能解释为什么拜登的平均,最大值都不如其他候选人.也是看出了支持拜登的更多是平民,而非资本家,相反前面两个异常的数据我们可以发现其捐赠额很大的都是一些公司,boss捐款,因为资本家的投入使得其最大值高,平均值大
4.分析选民的党派
党派在选举上有着决定作用,可以说什么党的票数多大概率就对应了什么党派候选人会胜选,当然特殊情况是多个候选人分摊了这个党派的票数,(尽管可能,但是这里不做考虑,一般都是一边倒,即使有分摊也不会出现大幅度拆分)
Y_CAND_PTY_AFFILIATION=df_data2.groupby('CAND_PTY_AFFILIATION').size().sort_values(ascending=False).head(5).values.tolist()
X_CAND_PTY_AFFILIATION=df_data2.groupby('CAND_PTY_AFFILIATION').size().sort_values(ascending=False).head(5).index.tolist()
from pyecharts.charts import Bar
Bar_YX=(
Bar(init_opts=opts.InitOpts(width='1900px',height='1000px',theme=ThemeType.CHALK))
.add_xaxis(X_CAND_PTY_AFFILIATION)
.add_yaxis('候选人党派获取支持票数',Y_CAND_PTY_AFFILIATION)
# .reversal_axis()
.set_global_opts(title_opts=opts.TitleOpts(title='候选人党派')
,toolbox_opts=opts.ToolboxOpts(is_show=True))
)
可以看出其中民主党占优势,为此查询了下拜登所在党派:
所以从各党派参与人数与候选人谁会胜选确实有关系
(感兴趣的可以使用过去很多年的选举数据在判断下,这里不做展开)
5.分析拜登在各个州获得的捐赠占比
主要分析对拜登的捐赠top10的州各自占比,说明拜登获得捐赠的主力在什么州
data=df_data2[df_data2['CAND_NAME']=='BIDEN, JOSEPH R JR']
data_y=data.groupby('STATE').sum().sort_values("TRANSACTION_AMT",ascending=False).head(10)['TRANSACTION_AMT'].tolist()
data_x=data.groupby('STATE').sum().sort_values("TRANSACTION_AMT",ascending=False).head(10).index.tolist()
sum1=sum(data_y)
data_y=[round(i/sum1*100,1) for i in data_y]
from pyecharts.charts import Pie
pie = (
Pie(init_opts=opts.InitOpts(width="1900px", height="1100px",theme=ThemeType.PURPLE_PASSION))
.add(
"各州捐款数占比",
[list(z) for z in zip(data_x, data_y)],
radius=["40%", "50%"],
center=[600,450],
label_opts=opts.LabelOpts(
position="outside",
formatter="{a|{a}}{abg|}\n{hr|}\n {b|{b}: }{c} {per|{d}%} ",
background_color="#eee",
border_color="#aaa",
border_width=1,
border_radius=4,
rich={
"a": {"color": "#999", "lineHeight": 22, "align": "center"},
"abg": {
"backgroundColor": "#e3e3e3",
"width": "100%",
"align": "right",
"height": 22,
"borderRadius": [4, 4, 0, 0],
},
"hr": {
"borderColor": "#aaa",
"width": "100%",
"borderWidth": 0.5,
"height": 0,
},
"b": {"fontSize": 16, "lineHeight": 33},
"per": {
"color": "#eee",
"backgroundColor": "#334455",
"padding": [2, 4],
"borderRadius": 2,
},
},
),
)
)
结果如下:
加利福尼亚州,内华达州是拜登的捐赠主力
6.分析各个州总捐款top10和对应的捐赠人数以及这几个州的人均捐赠数
分析各州参与选举的积极度和总捐款top10的各个州的人均捐款数
from pyecharts.charts import Bar
from pyecharts import options as opts
y=df_data2.groupby('STATE').sum().sort_values("TRANSACTION_AMT",ascending=False).head(10)['TRANSACTION_AMT'].tolist()
y=[round(i/1e7,3) for i in y]
# print(y)
x=df_data2.groupby('STATE').sum().sort_values("TRANSACTION_AMT",ascending=False).head(10).index.tolist()
c1=(
Bar(init_opts=opts.InitOpts(width="800px", height="600px"))
.add_xaxis(x)
.add_yaxis('TRANSACTION_AMT',y,itemstyle_opts=opts.ItemStyleOpts(color='Teal'),
label_opts=opts.LabelOpts(is_show=True, position='top', formatter="{c}",
color='cyan'))
# .reversal_axis()
.set_global_opts(
legend_opts=opts.LegendOpts(pos_left='left',pos_top='top'),
xaxis_opts=opts.AxisOpts(
name='STATE',
name_location='middle',
name_gap=30, # 与x轴线的距离
name_textstyle_opts=opts.TextStyleOpts(
font_family='Microsoft Yahei',
font_size=20,
),
axistick_opts=opts.AxisTickOpts(
is_show=True,
# is_show=False, # 是否显示
is_inside=True, # 刻度线是否在内侧
),
axisline_opts=opts.AxisLineOpts(
symbol='none',
linestyle_opts=opts.LineStyleOpts(
width=1,
color='black',
)
),
axislabel_opts=opts.LabelOpts(
rotate=40,
font_size=12,
font_family='Arial',
font_weight='bold'
),
),
yaxis_opts=opts.AxisOpts(
name='TRANSACTION_AMT_SUM(/1e7)',
name_location='middle',
name_gap=60,
min_=0,
max_=3,
name_textstyle_opts=opts.TextStyleOpts(
font_family='Times New Roman',
font_size=20,
color='black',
# font_weight='bolder',
),
axistick_opts=opts.AxisTickOpts(
is_show=False, # 是否显示
is_inside=True, # 刻度线是否在内侧
),
axislabel_opts=opts.LabelOpts(
font_size=12,
font_family='Times New Roman',
formatter="{value}" # y轴显示方式以数据形式
),
splitline_opts=opts.SplitLineOpts(is_show=True,linestyle_opts=opts.LineStyleOpts(color='black')), # y轴网格线
axisline_opts=opts.AxisLineOpts(is_show=False), # y轴线
),
toolbox_opts=opts.ToolboxOpts(is_show=True),
)
.set_series_opts(markline_opts=opts.MarkLineOpts(
data=[
opts.MarkLineItem(type_="average", name="平均值"),
opts.MarkLineItem(type_='min',name='最小值'),
opts.MarkLineItem(symbol="none", x="90%", y="max"),
opts.MarkLineItem(symbol="circle", type_="max", name="最高点"),
]
))
)
x1=df_data2.groupby('STATE').size().sort_values(ascending=False).head(10).index.tolist()
y1=df_data2.groupby('STATE').size().sort_values(ascending=False).head(10).tolist()
c2=(
Bar(init_opts=opts.InitOpts(width="800px", height="600px"))
.add_xaxis(x1)
.add_yaxis('TRANSACTION',y1,itemstyle_opts=opts.ItemStyleOpts(color='Navy'),label_opts=opts.LabelOpts(color='cyan'))
# .reversal_axis()
.set_global_opts(
datazoom_opts=opts.DataZoomOpts(is_show=True),
xaxis_opts=opts.AxisOpts(
name='STATE',
name_location='middle',
name_gap=30, # 与x轴线的距离
# name_Rorate设置旋转角度
# x轴名称的格式配置
name_textstyle_opts=opts.TextStyleOpts(
font_family='Microsoft Yahei',
font_size=20,
),
# 坐标轴刻度配置项
axistick_opts=opts.AxisTickOpts(
is_show=True,
# is_show=False, # 是否显示
is_inside=True, # 刻度线是否在内侧
),
# 坐标轴线的配置
axisline_opts=opts.AxisLineOpts(
linestyle_opts=opts.LineStyleOpts(
width=1,
color='black',
)
),
axislabel_opts=opts.LabelOpts(
rotate=40,
font_size=12,
font_family='Arial',
font_weight='bold'
),
),
yaxis_opts=opts.AxisOpts(
name='TRANSACTION_PERSON_NUMBER',
name_location='middle',
name_gap=50,
name_textstyle_opts=opts.TextStyleOpts(
font_family='Times New Roman',
font_size=20,
color='black',
# font_weight='bolder',
),
axistick_opts=opts.AxisTickOpts(
is_show=False, # 是否显示
is_inside=True, # 刻度线是否在内侧
),
axislabel_opts=opts.LabelOpts(
font_size=12,
font_family='Times New Roman',
formatter="{value}" # y轴显示方式以数据形式
),
splitline_opts=opts.SplitLineOpts(is_show=True,linestyle_opts=opts.LineStyleOpts(color='black')), # y轴网格线
axisline_opts=opts.AxisLineOpts(is_show=False), # y轴线
),
toolbox_opts=opts.ToolboxOpts(is_show=True),
)
.set_series_opts(markline_opts=opts.MarkLineOpts(
data=[
opts.MarkLineItem(type_="average", name="平均值"),
opts.MarkLineItem(type_='min',name='最小值'),
opts.MarkLineItem(symbol="none", x="90%", y="max"),
opts.MarkLineItem(symbol="circle", type_="max", name="最高点"),
]
))
)
from pyecharts.charts import Line
data_1=df_data2.groupby('STATE').size().sort_values(ascending=False).head(10).index.tolist()
data_2=df_data2.groupby('STATE').sum()['TRANSACTION_AMT']
data_2=[data_2[i] for i in data_1]
p=sum(data_2)
data_2=[round(i/p*100,2) for i in data_2]
line_1=(
Line(init_opts=opts.InitOpts(width="800px", height="500px",theme=ThemeType.PURPLE_PASSION))
.add_xaxis(data_1)
.add_yaxis('TRANSACTION_ATtop10_AVERAGE', y_axis=data_2,
)
.set_global_opts(
title_opts=opts.TitleOpts(title="捐赠人数排行前10的人均捐赠数目",pos_left='left',pos_top='center',
title_textstyle_opts=opts.TextStyleOpts( font_family='Times New Roman',
font_size=20,
color='black',)
),#一定程度上反应了州的经济水平
tooltip_opts=opts.TooltipOpts(trigger="axis"),
toolbox_opts=opts.ToolboxOpts(is_show=True),
xaxis_opts=opts.AxisOpts( name='STATE',
name_location='middle',
name_gap=50,
type_="category",
boundary_gap=False,
name_textstyle_opts=opts.TextStyleOpts(
font_family='Times New Roman',
font_size=20,
color='black',
),
axislabel_opts=opts.LabelOpts(
rotate=40)),
legend_opts=opts.LegendOpts(is_show=False),
yaxis_opts=opts.AxisOpts(
name='TRANSACTION_PERSON_NUMBER',
name_location='middle',
name_gap=50,
name_textstyle_opts=opts.TextStyleOpts(
font_family='Times New Roman',
font_size=20,
color='black',
# font_weight='bolder',
),
axistick_opts=opts.AxisTickOpts(
is_show=False, # 是否显示
is_inside=True, # 刻度线是否在内侧
),
axislabel_opts=opts.LabelOpts(
font_size=12,
font_family='Times New Roman',
formatter="{value}" # y轴显示方式以数据形式
),
axisline_opts=opts.AxisLineOpts(is_show=False), # y轴线
)
)
.set_series_opts(markline_opts=opts.MarkLineOpts(
data=[
opts.MarkLineItem(type_="average", name="平均值"),
opts.MarkLineItem(type_='min', name='最小值'),
opts.MarkLineItem(symbol="none", x="90%", y="max"),
opts.MarkLineItem(symbol="circle", type_="max", name="最高点"),
]
)
)
)
from pyecharts.charts import Grid
p1=(
Grid(init_opts=opts.InitOpts(width="1900px", height="1400px",theme=ThemeType.CHALK))
# Page(layout=Page.SimplePageLayout)
.add(c1,grid_opts=opts.GridOpts(pos_bottom='60%',pos_right='55%'))
.add(c2,grid_opts=opts.GridOpts(pos_bottom='60%',pos_left='55%'))
.add(line_1,grid_opts=opts.GridOpts(pos_top='60%',pos_right='50%'))
)
可以看出加利福尼亚州既是参与人数最多的也是捐款人数top10的州中人均捐款最多的,侧面看出加利福尼亚州经济应该比较好,于是我查询了2020年美国各州的GDP数据,发现加利福利亚州确实始终是美国经济最好的地方.其实我们熟知的硅谷就在加利福利亚州.另外很多世界TOP企业也在加利福利亚,列如APPLE,FACEBOOK,谷歌等等
另外我们分析到的数据中排名第二的纽约州也在GDPtop3的位置,我们也注意到捐赠数多的不一定经济发展好很可能只是选民参与的积极程度比较高
所以通过人均捐款数判断州的经济情况大概率上是可行的
(这里还可做个补充就是再单独对拜登的分析)
7.分析过去的一个月中每天捐赠数变化
from pyecharts.charts import Calendar
import datetime
from pyecharts import options as opts
data_dete=df_data2.groupby('TRANSACTION_DT').sum()['TRANSACTION_AMT'].values.tolist()
begin = datetime.date(2020, 7, 22)
end = datetime.date(2020, 8, 20)
data = [
[str(begin + datetime.timedelta(days=i)),data_dete[i] ]
for i in range((end - begin).days + 1)
]
import numpy as np
split=np.linspace(min(data_dete),max(data_dete),8)
end_split=[]
for i in range(0,7):
end_split.append({'min':split[i],'max':split[i+1]})
calendar=(
Calendar(init_opts=opts.InitOpts(width="1900px", height="800px",theme=ThemeType.PURPLE_PASSION))
.add(
series_name="",
yaxis_data=data,
calendar_opts=opts.CalendarOpts(
pos_top="120",
pos_left="30",
pos_right="30",
range_="2020",
yearlabel_opts=opts.CalendarYearLabelOpts(is_show=False),
),
# label_opts=opts.LabelOpts(color='purple')
)
.set_global_opts(
title_opts=opts.TitleOpts(pos_top="30", pos_left="center", title="过去一个月每天获得的捐款数"),
visualmap_opts=opts.VisualMapOpts(
max_=max(data_dete),
min_=min(data_dete),
orient="horizontal",
is_piecewise=True,
pos_top="center",
pos_left="center",
# is_inverse=True,
pieces=end_split,
textstyle_opts=opts.TextStyleOpts(color='write',font_size=20,font_family='Microsoft YaHei')
,item_height=20,item_width=30
),
)
)
可以看到最后一天是捐款数最多的一天,前面都比较平淡,这个大概率是情绪影响的,因为这一天是决定选举结果的一天,不止是候选人,还有选民都会比较感性.
8.分析过去一个月中总捐赠额top10的州每天捐赠流入情况
from pyecharts.charts import ThemeRiver
river=(
ThemeRiver(init_opts=opts.InitOpts(width='1900px',height='1000px',theme=ThemeType.CHALK))
.add(
series_name=OCCUPATION_top10,
data=dete_occupation_y,
singleaxis_opts=opts.SingleAxisOpts(
pos_top="50", pos_bottom="50", type_="time"
),
)
.set_global_opts(
tooltip_opts=opts.TooltipOpts(trigger="axis", axis_pointer_type="line")
,title_opts=opts.TitleOpts(title='总捐赠top10职业每天的捐赠流入'),
datazoom_opts=opts.DataZoomOpts(is_show=True),
)
)
其中7-27号纽约州捐款变化很大,猜测有较大概率是候选人在这个州拉票,或者发生了一些特殊的事情
于是我查询资料发现,作为候选人之一的特朗普就是纽约州出生的,并且7-27号是共和党全国代表大会的最后一天,想必作为特朗普的出生地纽约,在这一天选民也是比较激动的,所以出现大的波动很正常
9.分析过去一个月中总捐赠额top10的职业每天捐赠流入情况
river1=(
ThemeRiver(init_opts=opts.InitOpts(width='1900px',height='1000px',theme=ThemeType.CHALK))
.add(
series_name=STATE_top10,
data=dete_state_y,
singleaxis_opts=opts.SingleAxisOpts(
pos_top="50", pos_bottom="50", type_="time"
),
)
.set_global_opts(
tooltip_opts=opts.TooltipOpts(trigger="axis", axis_pointer_type="line")
,title_opts=opts.TitleOpts(title='总捐赠top10的州每天的捐赠流入'),
datazoom_opts=opts.DataZoomOpts(is_show=True),
)
)
同样发现27号这一天也是职业捐助不平常的一天,FOUNDER(创始人,这里看为资本家吧,毕竟特朗普也是商人)
10.分析总捐赠数top10的日期总捐赠人数和总捐赠数变化
# #先取出数据量前10的,然后再对日期排序
data_sum_y=df_data2.groupby('TRANSACTION_DT').sum().sort_values('TRANSACTION_AMT',ascending=True)['TRANSACTION_AMT'].head(10).values.tolist()
data_personsum_y=df_data2.groupby('TRANSACTION_DT').size().sort_values(ascending=True).head(10).values.tolist()
data_sum_x=df_data2.groupby('TRANSACTION_DT').sum().sort_values('TRANSACTION_AMT',ascending=True).head(10).index.tolist()
data_personsum_x=df_data2.groupby('TRANSACTION_DT').size().sort_values(ascending=True).head(10).index.tolist()
ans=list(zip(data_sum_x,data_sum_y))
ans1=list(zip(data_personsum_x,data_personsum_y))
ans=sorted(ans,key=(lambda x:x[0]))
ans1=sorted(ans1,key=(lambda x:x[0]))
data_sum_x=[i[0] for i in ans]
data_personsum_x=[i[0] for i in ans1]
data_sum_y=[i[1] for i in ans]
data_personsum_y=[i[1] for i in ans1]
#
from pyecharts.charts import Line
line=(
Line(init_opts=opts.InitOpts(width="1500px", height="380px",theme=ThemeType.CHALK))
.add_xaxis(data_sum_x)
.add_yaxis('data_personsum', y_axis=data_personsum_y,
markline_opts=opts.MarkLineOpts(
data=[
opts.MarkLineItem(type_="average", name="平均值"),
opts.MarkLineItem(symbol="none", x="90%", y="max"),
opts.MarkLineItem(symbol="circle", type_="max", name="最高点"),
]
),
)
.set_global_opts(
yaxis_opts=opts.AxisOpts(min_=13000),
title_opts=opts.TitleOpts(title="过去某10天总捐款人数/总捐款数"),
tooltip_opts=opts.TooltipOpts(trigger="axis"),
toolbox_opts=opts.ToolboxOpts(is_show=True),
xaxis_opts=opts.AxisOpts(type_="category", boundary_gap=False),
)
)
line1=(
Line(init_opts=opts.InitOpts(width="1500px", height="380px"))
.add_xaxis(data_sum_x)
.add_yaxis('data_sum',y_axis=data_sum_y,
markline_opts=opts.MarkLineOpts(
data=[
opts.MarkLineItem(type_="average", name="平均值"),
opts.MarkLineItem(symbol="none", x="90%", y="max"),
opts.MarkLineItem(symbol="circle", type_="max", name="最高点"),
]
),
)
.set_global_opts(
yaxis_opts=opts.AxisOpts(min_=1300000),
# title_opts=opts.TitleOpts(title="过去某10天总捐款情况"),
tooltip_opts=opts.TooltipOpts(trigger="axis"),
toolbox_opts=opts.ToolboxOpts(is_show=True),
xaxis_opts=opts.AxisOpts(type_="category", boundary_gap=False),
)
)
from pyecharts.charts import Grid
page=(#page是最上层的图表不能嵌入到其他图表之中
# Page()
Grid(init_opts=opts.InitOpts(width="1900px", height="1000px",theme=ThemeType.CHALK))
.add(line,grid_opts=opts.GridOpts(pos_bottom='55%'))
.add(line1,grid_opts=opts.GridOpts(pos_top='55%'))
)
如果如下:
发现异常数据8.3号和8.8号这两天捐赠人数和捐赠数成反比例分布
所以我们单独对8.3号和8.8号这两天单独分析
11.分析其中产生差错的原因
#一般认为捐款的人数越多其捐款总数就会越大但是发现有两天人数与捐款数差距,所以我们具体分析这两天,并加入
#一般的一天作为对照组 2020803 2020808 +2020725 由分析各个属性最有可能就是捐赠人职业的影响
y11=df_data2[df_data2.TRANSACTION_DT=='2020803'].groupby('OCCUPATION').sum().sort_values('TRANSACTION_AMT',ascending=False).head(10).sort_values('OCCUPATION')['TRANSACTION_AMT'].values.tolist()
x11=df_data2[df_data2.TRANSACTION_DT=='2020803'].groupby('OCCUPATION').sum().sort_values('TRANSACTION_AMT',ascending=False).head(10).sort_values('OCCUPATION')['TRANSACTION_AMT'].index.tolist()
y11_person=df_data2[df_data2.TRANSACTION_DT=='2020803'].groupby('OCCUPATION').size()
sum_y11=sum(y11)
y11_bi=[round(i/sum_y11*100/y11_person[x11[j]],4) for j,i in enumerate(y11)]#每个职业在总金额的占比
y12=df_data2[df_data2.TRANSACTION_DT=='2020808'].groupby('OCCUPATION').sum().sort_values('TRANSACTION_AMT',ascending=False).head(10).sort_values('OCCUPATION')['TRANSACTION_AMT'].values.tolist()
x12=df_data2[df_data2.TRANSACTION_DT=='2020808'].groupby('OCCUPATION').sum().sort_values('TRANSACTION_AMT',ascending=False).head(10).sort_values('OCCUPATION')['TRANSACTION_AMT'].index.tolist()
y12_person=df_data2[df_data2.TRANSACTION_DT=='2020808'].groupby('OCCUPATION').size()
sum_y12=sum(y12)
y12_bi=[round(i/sum_y12*100/y12_person[x12[j]],4) for j,i in enumerate(y12)]
y13=df_data2[df_data2.TRANSACTION_DT=='2020725'].groupby('OCCUPATION').sum().sort_values('TRANSACTION_AMT',ascending=False).head(10).sort_values('OCCUPATION')['TRANSACTION_AMT'].values.tolist()
x13=df_data2[df_data2.TRANSACTION_DT=='2020725'].groupby('OCCUPATION').sum().sort_values('TRANSACTION_AMT',ascending=False).head(10).sort_values('OCCUPATION')['TRANSACTION_AMT'].index.tolist()
y13_person=df_data2[df_data2.TRANSACTION_DT=='2020725'].groupby('OCCUPATION').size()
sum_y13=sum(y13)
y13_bi=[round(i/sum_y13*100/y13_person[x13[j]],4) for j,i in enumerate(y13)]
# 做柱形图
l11=(
Bar(init_opts=opts.InitOpts(width="1900px", height="400px",theme=ThemeType.DARK))
.add_xaxis(x11)
.add_yaxis('data_personsum', y_axis=y11,bar_width='50%',
itemstyle_opts=opts.ItemStyleOpts(color='blue'),
markline_opts=opts.MarkLineOpts(
data=[
opts.MarkLineItem(type_="average", name="平均值"),
opts.MarkLineItem(symbol="none", x="90%", y="max"),
opts.MarkLineItem(symbol="circle", type_="max", name="最高点"),
]
),
)
.set_global_opts(
title_opts=opts.TitleOpts(title="过去某10天总捐款人数2020-08-03"),
tooltip_opts=opts.TooltipOpts(trigger="axis"),
toolbox_opts=opts.ToolboxOpts(is_show=True),
xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(
rotate=40)),
)
)
l21=(
Bar(init_opts=opts.InitOpts(width="1900px", height="400px",theme=ThemeType.DARK))
.add_xaxis(x12)
.add_yaxis('data_personsum', y_axis=y12,bar_width='50%',
itemstyle_opts=opts.ItemStyleOpts(color='red'),
markline_opts=opts.MarkLineOpts(
data=[
opts.MarkLineItem(type_="average", name="平均值"),
opts.MarkLineItem(symbol="none", x="90%", y="max"),
opts.MarkLineItem(symbol="circle", type_="max", name="最高点"),
]
),
)
.set_global_opts(
title_opts=opts.TitleOpts(title="过去某10天总捐款人数2020-08-08"),
tooltip_opts=opts.TooltipOpts(trigger="axis"),
toolbox_opts=opts.ToolboxOpts(is_show=True),
xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(
rotate=40)),
)
)
l31=(
Bar(init_opts=opts.InitOpts(width="1900px", height="400px",theme=ThemeType.DARK))
.add_xaxis(x13)
.add_yaxis('data_personsum', y_axis=y13,bar_width='50%',
itemstyle_opts=opts.ItemStyleOpts(color='green'),
# yaxis=opts.AxisOpts(min_=1300000),
markline_opts=opts.MarkLineOpts(
data=[
opts.MarkLineItem(type_="average", name="平均值"),
opts.MarkLineItem(symbol="none", x="90%", y="max"),
opts.MarkLineItem(symbol="circle", type_="max", name="最高点"),
]
),
)
.set_global_opts(
title_opts=opts.TitleOpts(title="过去某10天总捐款人数2020-07-25"),
tooltip_opts=opts.TooltipOpts(trigger="axis"),
toolbox_opts=opts.ToolboxOpts(is_show=True),
xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(
rotate=40)),
)
)
l1=(
Line(init_opts=opts.InitOpts(width="1900px", height="400px",theme=ThemeType.DARK))
.add_xaxis(x11)
.add_yaxis('data_personsum', y_axis=y11_bi,
itemstyle_opts=opts.ItemStyleOpts(color='blue'),
markline_opts=opts.MarkLineOpts(
data=[
opts.MarkLineItem(type_="average", name="平均值"),
opts.MarkLineItem(symbol="none", x="90%", y="max"),
opts.MarkLineItem(symbol="circle", type_="max", name="最高点"),
]
),
)
.set_global_opts(
title_opts=opts.TitleOpts(title="过去某10天 总捐款额前10职业的个人占比2020-08-03"),
tooltip_opts=opts.TooltipOpts(trigger="axis"),
toolbox_opts=opts.ToolboxOpts(is_show=True),
xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(
rotate=40)),
)
)
l2=(
Line(init_opts=opts.InitOpts(width="1900px", height="400px",theme=ThemeType.DARK))
.add_xaxis(x12)
.add_yaxis('data_personsum', y_axis=y12_bi,
itemstyle_opts=opts.ItemStyleOpts(color='red'),
markline_opts=opts.MarkLineOpts(
data=[
opts.MarkLineItem(type_="average", name="平均值"),
opts.MarkLineItem(symbol="none", x="90%", y="max"),
opts.MarkLineItem(symbol="circle", type_="max", name="最高点"),
]
),
)
.set_global_opts(
# yaxis_opts=opts.AxisOpts(max_=1.5),
title_opts=opts.TitleOpts(title="过去某10天 总捐款额前10职业的个人占比2020-08-08"),
tooltip_opts=opts.TooltipOpts(trigger="axis"),
toolbox_opts=opts.ToolboxOpts(is_show=True),
xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(
rotate=40)),
)
)
l3=(
Line(init_opts=opts.InitOpts(width="1900px", height="400px",theme=ThemeType.DARK))
.add_xaxis(x13)
.add_yaxis('data_personsum', y_axis=y13_bi,
itemstyle_opts=opts.ItemStyleOpts(color='green'),
# yaxis=opts.AxisOpts(min_=1300000),
markline_opts=opts.MarkLineOpts(
data=[
opts.MarkLineItem(type_="average", name="平均值"),
opts.MarkLineItem(symbol="none", x="90%", y="max"),
opts.MarkLineItem(symbol="circle", type_="max", name="最高点"),
]
),
)
.set_global_opts(
title_opts=opts.TitleOpts(title="过去某10天 总捐款额前10职业的个人占比2020-07-25"),
tooltip_opts=opts.TooltipOpts(trigger="axis"),
toolbox_opts=opts.ToolboxOpts(is_show=True),
xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(
rotate=40)),
)
)
page1=(
Page()
.add(l11,l21,l31)
)
page2=(
Page()
.add(l1,l2,l3)
)
结果如下:
分析图1我们发现其中8-3号这天,主力职业(RETIRED,NOT EMPLOYED)流入增加,并结合图二发现这一天还有高薪职业的流入,比如 PRIVATE EQUITY单个人就占这一天的1.48%,所以我们猜测这一天还有一些高薪职业的流入所以导致其人数减少捐赠数增加,相反8-8号这天,主力职业减少,并且相对正常的7-25号各职业个人占比都没有特别明显增加,使得这一天虽然人数增加,但是总捐赠减少.
END…
创作不易留下你的三连吧!
代码见github:https://github.com/CV-LS/data_analysis/tree/main
致谢
感谢您对本项目的支持和关注!如果您觉得这个项目对您有所帮助,请考虑给它一个星标(star)或 fork。您的支持是我们持续改进和发展的动力。