3 Python数据分析 美国各州人口分析案例 Pandas高级操作 美国大选献金案例 matplotlib

Python数据分析

1 案例 美国各州人口分析

1.1 数据介绍

数据来源:https://github.com/jakevdp/data-USstates/

1.1.1 州人口数量表 state-population.csv
字段字段名备注
state/region州/区域州简称,与state-abbrevs.csv文件中的abbreviation字段对应
ages人口年龄选项包括18岁以下under18和全部年龄段total
year年份
population人口数量
1.1.2 州面积表 state-areas.csv
字段字段名备注
state州名称州全称,与state-abbrevs.csv文件中的state字段对应
area (sq. mi)州面积
1.1.3 州简称对照表 state-abbrevs.csv
字段字段名备注
state州全称
abbreviation州简称
1.2 需求

将人口数据与各州简称数据进行合并,对合并数据中重复的abbreviation列进行删除;
找到使state的值为NaN的state/region,补上合适的值;
找到并删除area(sq.mi)列中的缺失数据所在行;
获取2010年的全民人口数据;
计算各州的人口密度,排序并获取人口密度最高的州。

1.3 分析:州人口数据-州简称数据
1.3.1 导入数据
import numpy as np
import pandas as pd
from pandas import Series, DataFrame

# 州人口数量表
popu_df = pd.read_csv('./state-population.csv')
popu_df.head()
'''
    state/region     ages    year    population
0             AL  under18    2012     1117489.0
1             AL    total    2012     4817528.0
2             AL  under18    2010     1130966.0
3             AL    total    2010     4785570.0
4             AL  under18    2011     1125763.0
'''

# 州面积表
area_df = pd.read_csv('./state-areas.csv')
area_df.head()
'''
        state   area (sq. mi)
0     Alabama           52423
1      Alaska          656425
2     Arizona          114006
3    Arkansas           53182
4  California          163707
'''

# 州简称对照表
abbr_df = pd.read_csv('./state-abbrevs.csv')
abbr_df.head()
'''
		state 	abbreviation
0 	  Alabama 			  AL
1 	   Alaska 			  AK
2 	  Arizona 			  AZ
3 	 Arkansas 			  AR
4  California 			  CA
'''
1.3.2 合并数据:州人口数据-州简称数据

将州人口数据与州简称数据进行合并,删除重复列。

# 合并
popu_abbr_df = pd.merge(left=popu_df, right=abbr_df, left_on='state/region', right_on='abbreviation', how='outer')
# 删除重复列abbreviation
popu_abbr_df.drop(labels='abbreviation', axis=1, inplace=True)
1.3.3 缺失值处理

判断是否存在缺失值

popu_abbr_df.info()
'''
<class 'pandas.core.frame.DataFrame'>
Int64Index: 2544 entries, 0 to 2543
Data columns (total 5 columns):
 #   Column        Non-Null Count  Dtype  
---  ------        --------------  -----  
 0   state         2448 non-null   object 
 1   state/region  2544 non-null   object 
 2   ages          2544 non-null   object 
 3   year          2544 non-null   int64  
 4   population    2524 non-null   float64
dtypes: float64(1), int64(1), object(3)
memory usage: 119.2+ KB
'''

可以看出,数据一共有2544条,但state列和population列数据量小于2544条,因此这两列中存在缺失数据。

popu_abbr_df.isnull().any(axis=0)
'''
state            True
state/region    False
ages            False
year            False
population       True
dtype: bool
'''

观察缺失值

nan_df = popu_abbr_df.loc[popu_abbr_df.isnull().any(axis=1)]
nan_df.head()
'''
        state   state/region     ages    year    population
2448      NaN             PR  under18    1990           NaN
2449      NaN             PR    total    1990           NaN
2450      NaN             PR    total    1991           NaN
2451      NaN             PR  under18    1991           NaN
2452      NaN             PR    total    1993           NaN
'''

nan_df['state/region'].unique()
# array(['PR', 'USA'], dtype=object)

说明简称PR和USA没有对应的全称。

pr_indexs = popu_abbr_df.loc[popu_abbr_df['state/region'] == 'PR'].index
popu_abbr_df.loc[pr_indexs, 'state'] = 'Puerto Rico'
usa_indexs = popu_abbr_df.loc[popu_abbr_df['state/region'] == 'USA'].index
popu_abbr_df.loc[usa_indexs, 'state'] = 'United State'

删除population列的缺失数据所在行

nan_indexs = popu_abbr_df.loc[popu_abbr_df['population'].isnull()].index
popu_abbr_df.drop(labels=nan_indexs, axis=0, inplace=True)
popu_abbr_df.info()
'''
popu_abbr_df.info()

<class 'pandas.core.frame.DataFrame'>
Int64Index: 2524 entries, 0 to 2543
Data columns (total 5 columns):
 #   Column        Non-Null Count  Dtype  
---  ------        --------------  -----  
 0   state         2524 non-null   object 
 1   state/region  2524 non-null   object 
 2   ages          2524 non-null   object 
 3   year          2524 non-null   int64  
 4   population    2524 non-null   float64
dtypes: float64(1), int64(1), object(3)
memory usage: 118.3+ KB
'''
1.3.4 ages列分析

ages列中的数据选项

popu_abbr_df['ages'].unique()
# array(['under18', 'total'], dtype=object)

查看ages列中不同选项出现的次数

popu_abbr_df['ages'].value_counts()
'''
total      1262
under18    1262
Name: ages, dtype: int64
'''
1.4 分析:州人口数据-州面积数据
1.4.1 合并数据:州人口数据-州面积数据
popu_area_df = pd.merge(left=popu_abbr_df, right=area_df, on='state', how='outer')
popu_area_df.info()
'''
<class 'pandas.core.frame.DataFrame'>
Int64Index: 2524 entries, 0 to 2523
Data columns (total 6 columns):
 #   Column         Non-Null Count  Dtype  
---  ------         --------------  -----  
 0   state          2524 non-null   object 
 1   state/region   2524 non-null   object 
 2   ages           2524 non-null   object 
 3   year           2524 non-null   int64  
 4   population     2524 non-null   float64
 5   area (sq. mi)  2476 non-null   float64
dtypes: float64(2), int64(1), object(3)
memory usage: 138.0+ KB
'''
1.4.2 缺失值处理
nan_indexs = popu_area_df.loc[popu_area_df['area (sq. mi)'].isnull()].index
popu_area_df.drop(labels=nan_indexs, axis=0, inplace=True)

popu_area_df.info()
'''
<class 'pandas.core.frame.DataFrame'>
Int64Index: 2476 entries, 0 to 2475
Data columns (total 6 columns):
 #   Column         Non-Null Count  Dtype  
---  ------         --------------  -----  
 0   state          2476 non-null   object 
 1   state/region   2476 non-null   object 
 2   ages           2476 non-null   object 
 3   year           2476 non-null   int64  
 4   population     2476 non-null   float64
 5   area (sq. mi)  2476 non-null   float64
dtypes: float64(2), int64(1), object(3)
memory usage: 135.4+ KB
'''
1.4.3 找出2010年的全民人口数据

条件查询

popu_area_df.query('year == 2010 & ages == "total"')
1.4.4 人口密度排序

计算人口密度

popu_area_df['population density'] = popu_area_df['population'] / popu_area_df['area (sq. mi)']

人口密度排序(降序)

popu_area_df.sort_values(by='population density', axis=0, ascending=False)

2 Pandas高级操作

2.1 替换操作 replace
df.replace(to_replace=原值, value=替换值) 

替换操作可以作用于Series和DataFrame中。

2.1.1 单值替换
import numpy as np
import pandas as pd
from pandas import DataFrame

df = DataFrame(data=np.random.randint(0, 10, size=(3, 6)))
'''
 	0 	1 	2 	3 	4 	5
0 	2 	4 	8 	9 	8 	0
1 	6 	1 	3 	8 	0 	2
2 	3 	6 	7 	9 	8 	4
'''

普通替换:替换所有符合要求的元素。

re_df1 = df.replace(to_replace=0, value='zero') 
'''
	0 	1 	2 	3 		4 		5
0 	2 	4 	8 	9 		8 	 zero
1 	6 	1 	3 	8 	 zero 		2
2 	3 	6 	7 	9 		8 		4
'''
2.1.2 多值替换
re_df2 = df.replace(to_replace={6:'six', 2:'two'})
'''
		0 		1 	2 	3 	4 		5
0 	  two 	    4 	8 	9 	8 		0
1 	  six 		1 	3 	8 	0     two
2 	    3 	  six 	7 	9 	8 		4
'''
2.1.3 定列替换

将第3列的数字9替换为字符串nine。

re_df3 = df.replace(to_replace={3: 9}, value='nine')
'''
	0 	1 	2 		3 	4 	5
0 	2 	4 	8 	 nine 	8 	0
1 	6 	1 	3 		8 	0 	2
2 	3 	6 	7 	 nine 	8 	4
'''
2.2 映射操作 map

映射:根据映射关系表,把一个元素和一个特定的标签或字符串绑定在一起,可以为元素提供不同的表现形式。
map方法是调用者的数据作为参数依次传入到映射字典或函数中,得到映射后的值。
map方法是Series的方法,只能被Series对象调用。

name_salary_dict = {
    'name': ['Jay', 'Tom', 'Jay'],
    'salary': [1000, 2000, 1000]
}
name_salary_df = DataFrame(data=name_salary_dict)
'''
	name 	salary
0 	 Jay 	  1000
1 	 Tom 	  2000
2 	 Jay 	  1000
'''

映射关系列表

mapping_dict = {
    'Jay': '杰',
    'Tom': '汤姆'
}
name_salary_df['name_chs'] = name_salary_df['name'].map(mapping_dict)
'''
	name 	salary 	name_chs
0 	 Jay 	  1000 		  杰
1 	 Tom 	  2000 		汤姆
2 	 Jay 	  1000 		  杰
'''
2.3 运算操作 map,apply

参考上表中的数据,工资超过1000的部分需要扣除50%的费用,计算每个人的薪资。

def calc_salary(salary):
	if salary >= 1000:
		salary = (salary - 1000) * 0.5
	return salary
2.3.1 map

map方法将函数作用于调用者Series对象中的每个元素。
map方法只能被Series对象调用,只能传入一个参数。

name_salary_df['salary_real'] = name_salary_df['salary'].map(calc_salary)
2.3.2 apply
  1. Series
    apply支持传入多个参数。

工资超过基数base的部分需要扣除50%的费用,计算每个人的薪资。

def calc_salary(salary, base):
	if salary >= base:
		salary = (salary - base) * 0.5
	return salary

name_salary_df['salary_real'] = name_salary_df['salary'].apply(calc_salary, args=(500,))
'''
	name 	salary 	name_chs 	salary_real
0 	 Jay 	  1000 		  杰 		  250.0
1 	 Tom 	  2000 	    汤姆 		  750.0
2 	 Jay 	  1000 		  杰 		  250.0
'''
  1. DataFrame
    apply方法可以将函数作用于DataFrame中的每行或每列。

每人加工资100元。

name_salary_df.apply(lambda x: x + 100 if x.name in ['salary', 'salary_real'] else x, axis=0)
'''
 	name 	salary 	name_chs 	salary_real
0 	 Jay 	  1100 		  杰 		  350.0
1 	 Tom 	  2100 		 汤姆 		  850.0
2 	 Jay 	  1100 		  杰 		  350.0
'''
2.4 随机抽样
2.4.1 numpy.random.permutation

permutation方法用于打乱原来数据中元素的顺序。
输入整数,返回打乱顺序的数组;
输入数组或列表,返回打乱顺序的数组。

np.random.permutation(3)  # array([0, 2, 1])
np.random.permutation(['a', 'b', 'c', 'd'])  # array(['c', 'a', 'd', 'b'], dtype='<U1')
2.4.2 take

take方法用于沿指定轴向返回给定位置索引中的元素。
axis=0表示行,axis=1表示列。

2.4.3 take方法 + permutation方法实现随机抽样

随机抽样的本质是将原始数据的行/列索引打乱。

# 生成数据
df = DataFrame(data=np.random.randint(0, 100, size=(100, 3)),columns=['A', 'B', 'C'])
# 打乱列索引。
df1 = df.take(indices=np.random.permutation(3), axis=1)
# 在上面的基础上打乱行索引。
df2 = df1.take(indices=np.random.permutation(100), axis=0)

df2.head()
'''
	B 	A 	C
13 	94 	91 	46
34 	90 	32 	72
87 	85 	70 	49
48 	19 	2 	10
1 	80 	48 	36
'''
2.5 分类处理 groupby方法,groups属性
2.5.1 groupby方法,groups属性

groupby方法用于对数据内部进行分组处理。
groups属性用于查看分组结果。

df = DataFrame({
    'item': ['Apple', 'Banana', 'Orange', 'Banana', 'Orange', 'Apple'],
    'price': [4, 3, 3, 2.5, 4, 2],
    'color': ['red', 'yellow', 'yellow', 'green', 'green', 'green'],
    'weight': [12, 20, 50, 30, 20, 44],
})
'''
	item 	price 	color 	weight
0 	Apple 	4.0 	red 	12
1 	Banana 	3.0 	yellow 	20
2 	Orange 	3.0 	yellow 	50
3 	Banana 	2.5 	green 	30
4 	Orange 	4.0 	green 	20
5 	Apple 	2.0 	green 	44
'''
df.groupby(by='item').groups
'''
{'Apple': Int64Index([0, 5], dtype='int64'),
 'Banana': Int64Index([1, 3], dtype='int64'),
 'Orange': Int64Index([2, 4], dtype='int64')}
'''

计算每一种水果的平均价格。

mean_price_series = df.groupby(by='item')['price'].mean()
'''
item
Apple     3.00
Banana    2.75
Orange    3.50
Name: price, dtype: float64
'''
2.5.2 配合映射操作

配合映射操作(match),将每种水果的平均价格汇总到源数据中。

mean_price_series = df.groupby(by='item')['price'].mean()
# 映射字典
mean_price_dict = mean_price_series.to_dict()  # {'Apple': 3.0, 'Banana': 2.75, 'Orange': 3.5}
df['mean_price'] = df['item'].map(mean_price_dict)

将每种颜色的水果的平均重量汇总到源数据中。

every_color_mean_weight_series = df.groupby(by='color')['weight'].mean()
df['every_color_mean_weight'] = df['color'].map(every_color_mean_weight_series.to_dict())
2.6 高级聚合操作

对数据使用groupby进行分组后,可以通过transform或apply提供函数或lambda表达式来实现更多自定义操作。

df.groupby(‘item’)[‘price’].sum() <=> df.groupby(‘item’)[‘price’].apply(sum)

def my_mean(s):
    sum = 0
    for i in s:
        sum += i
    return sum / len(s)

df.groupby(by='item')['price'].apply(my_mean)
'''
item
Apple     3.00
Banana    2.75
Orange    3.50
Name: price, dtype: float64
'''

df.groupby(by='item')['price'].transform(my_mean)
'''
0    3.00
1    2.75
2    3.50
3    2.75
4    3.50
5    3.00
Name: price, dtype: float64
'''

apply和transform的区别:
apply返回的是对分类后数据的操作结果,不会与原数据进行映射操作;
transform返回的结果是经过进一步映射后的结果。

2.7 数据加载 read_csv
2.7.1 读取.txt类型的文件数据

read_csv的参数header的默认值是infer,会将第一行数据作为列名。

df = pd.read_csv('./type-.txt')
'''
	你好-我好-他也好
0 	也许-大概-有可能
1 	然而-未必-不见得
'''

参数header=None表明原始文件数据没有列索引,read_csv会自动添加列索引。

df = pd.read_csv('./type-.txt', header=None)
'''
	0
0 	你好-我好-他也好
1 	也许-大概-有可能
2 	然而-未必-不见得
'''

参数sep用于指定分隔符。

df = pd.read_csv('./type-.txt', header=None, sep='-')
'''
	0 		1 		2
0 	你好 	我好 	他也好
1 	也许 	大概 	有可能
2 	然而 	未必 	不见得
'''

参数names用于手动指定列名。

df = pd.read_csv('./type-.txt', header=None, sep='-', names=['A', 'B', 'C'])
'''
	A 		B 		C
0 	你好 	我好 	他也好
1 	也许 	大概 	有可能
2 	然而 	未必 	不见得
'''
'''
2.7.2 读取数据库中的数据
import sqlite3 as sqlite3

# 连接数据库,获取连接对象。
conn = sqlite3.connect('./weather_2012.sqlite')
# 读取数据库中的数据。
sql_df = pd.read_sql('select * from weather_2012', conn)

# 将指定df中的数据值存储到数据库中。
df = pd.read_csv('./type-.txt', header=None, sep='-')
df.to_sql('type', conn)
pd.read_sql('select * from type', conn)
'''
 	index 	0 		1 		2
0 	0 		你好 	我好 	他也好
1 	1 		也许 	大概 	有可能
2 	2 		然而 	未必 	不见得
'''
2.8 透视表 pivot_table

数据透视表(Pivot Table)是一种可以对数据动态排布并且分类汇总的表格格式。

Pandas中的建立数据透视表的方法pivot_table

pivot_table(data, values=None, index=None, columns=None,aggfunc='mean', fill_value=None, margins=False, dropna=True, margins_name='All')

重要参数:index,values,columns,aggfunc

2.8.1 准备数据

数据集是火箭队球星James Harden在某一赛季比赛数据

df = pd.read_csv('./透视表-篮球赛.csv')
df.head()
'''
	对手 	胜负 	主客场 	命中 	投篮数 	投篮命中率 	3分命中率 	篮板 	助攻 	得分
0 	勇士 	胜 		客 		10 		23 		0.435 		0.444 		6 		11 		27
1 	国王 	胜 		客 		8 		21 		0.381 		0.286 		3 		9 		27
2 	小牛 	胜 		主 		10 		19 		0.526 		0.462 		3 		7 		29
3 	灰熊 	负 		主 		8 		20 		0.400 		0.250 		5 		8 		22
4 	76人 	胜 		客 		10 		20 		0.500 		0.250 		3 		13 		27
'''
2.8.2 index参数

index参数用于指定分类汇总的分类条件。

需求:查看哈登对阵每个对手不同主客场下的数据。
分类条件为对手和主客场。

df.pivot_table(index=['对手','主客场'])
'''
 				3分命中率 	助攻 	命中 	得分 	投篮命中率 	投篮数 	篮板
对手 	主客场
76人 	主 		0.4290 		7.0 	8.0 	29.0 	0.381 		21.0 	4.0
		客 		0.2500 		13.0 	10.0 	27.0 	0.500 		20.0 	3.0
勇士 	客 		0.4440 		11.0 	10.0 	27.0 	0.435 		23.0 	6.0
...
'''
2.8.3 values参数

values参数用于对数据进行筛选。
需求:查看哈登在不同主客场和不同胜负情况下的平均得分、平均篮板和平均助攻三项数据。

df.pivot_table(index=['主客场', '胜负'], values=['得分', '篮板', '助攻'])
'''
 				助攻 		得分 		篮板
主客场 	胜负 			
主 		胜 		10.555556 	34.222222 	5.444444
		负 		8.666667 	29.666667 	5.000000
客 		胜 		9.000000 	32.000000 	4.916667
		负 		8.000000 	20.000000 	4.000000
'''
2.8.4 aggfunc参数

aggfunc参数用于指定对数据聚合时进行的函数操作,默认操作是计算均值mean。
需求:查看哈登在不同主客场和不同胜负情况下的总得分、总篮板、总助攻三项数据。

df.pivot_table(index=['主客场', '胜负'], values=['得分', '篮板', '助攻'], aggfunc='sum')
'''
				助攻 	得分 	篮板
主客场 	胜负 			
主 		胜 		95 		308 	49
		负 		26 		89 		15
客 		胜 		108 	384 	59
		负 		8 		20 		4
'''
2.8.5 columns参数

columns参数用于设置列层次字段,对values字段进行分类。
需求:查看主客场下对阵的每个对手的得分情况。

总得分

df.pivot_table(index='主客场', values='得分', aggfunc='sum')
'''
 		得分
主客场 	
主 		397
客 		404
'''

在总得分的基础上查看在每个对手维度上的得分部分,空值补0。

df.pivot_table(index='主客场', values='得分', aggfunc='sum', columns='对手', fill_value=0)
'''
对手 	76人 	勇士 	国王 	太阳 	小牛 	尼克斯 	开拓者 	掘金 	步行者 	湖人 	灰熊 	爵士 	猛龙 	篮网 	老鹰 	骑士 	鹈鹕 	黄蜂
主客场
主 		29 		0		0		0		29		37		0		21		29		0		60		56		38		37		0		35		26		0
客 		27 		27		27		48		0		31		48		0		26		36		49		29		0		0		29		0		0		27
'''
2.9 交叉表 crosstab

交叉表(Cross Tabulations)是一种常用的分类汇总表格,是用于计算分组的特殊透视表。

df.crosstab(index, colums)

index用于指定交叉表的行索引;
columns用于指定交叉表的列索引。

准备数据

df = DataFrame({
    'sex': ['man', 'man', 'women', 'women', 'man', 'women', 'man', 'women', 'women'],
    'age': [15, 23, 25, 17, 35, 57, 24, 31, 22],
    'smoke': [True, False, False, True, True, False, False, True, False],
    'height': [168, 179, 181, 166, 173, 178, 188, 190, 160]
})
'''
	sex 	age 	smoke 	height
0 	man 	15 		True 	168
1 	man 	23 		False 	179
2 	women 	25 		False 	181
3 	women 	17 		True 	166
4 	man 	35 		True 	173
5 	women 	57 		False 	178
6 	man 	24 		False 	188
7 	women 	31 		True 	190
8 	women 	22 		False 	160
'''

需求1:获取各性别的抽烟人数。

pd.crosstab(index=df.smoke, columns=df.sex)
'''
sex 	man 	women
smoke 		
False 	2 		3
True 	2 		2
'''

需求2:判断各个年龄段的人是否抽烟。

pd.crosstab(index=df.age, columns=df.smoke)
'''
smoke 	False 	True
age 		
15 		0 		1
17 		0 		1
22 		1 		0
23 		1 		0
24 		1 		0
25 		1 		0
31 		0 		1
35 		0 		1
57 		1 		0
'''

3 案例 2012年美国大选献金数据分析

3.1 数据介绍

导入数据

import numpy as np
import pandas as pd

df = pd.read_csv('./data/usa_election.txt')

重要字段介绍

字段名描述
cand_nm候选人姓名
contbr_nm捐赠人姓名
contbr_st捐赠人所在州
contbr_employer捐赠人所在公司
contbr_occupation捐赠人职业
contb_receipt_amt捐赠数额(美元)
contb_receipt_dt捐款日期
3.2 需求
  1. 导入数据,并进行统计描述;
  2. 处理缺失值,空值填充为NOT PROVIDE;
  3. 处理异常值,将捐款金额小于0的数据删除;
  4. 新建列party,表示各个候选人所在党派;
  5. 查看party列中有哪些不同的元素;
  6. 统计party列中各个值出现的次数;
  7. 查看各个党派收到的政治献金总额contb_receipt_amt;
  8. 查看具体每天各个党派收到的政治献金总额contb_receipt_amt;
  9. 将表中日期格式转换为’yyyy-mm-dd’;
  10. 查看老兵(捐献者职业为DISABLED VETERAN)主要支持谁。
3.3 准备数据
3.3.1 导入数据
df = pd.read_csv('./usa_election.txt')
df.shape  # (536041, 16)
df.head()
'''
	cmte_id 	cand_id 	cand_nm 			contbr_nm 			contbr_city 		contbr_st 		contbr_zip 		contbr_employer 		contbr_occupation 		contb_receipt_amt 	contb_receipt_dt 	receipt_desc 	memo_cd 	memo_text 	form_tp 	file_num
0 	C00410118 	P20002978 	Bachmann, Michelle 	HARVEY, WILLIAM 	MOBILE 				AL 				3.6601e+08 		RETIRED 				RETIRED 				250.0 				20-JUN-11 			NaN 			NaN 		NaN 		SA17A 		736166
1 	C00410118 	P20002978 	Bachmann, Michelle 	HARVEY, WILLIAM 	MOBILE 				AL 				3.6601e+08 		RETIRED 				RETIRED 				50.0 				23-JUN-11 			NaN 			NaN 		NaN 		SA17A 		736166
2 	C00410118 	P20002978 	Bachmann, Michelle 	SMITH, LANIER 		LANETT 				AL 				3.68633e+08 	INFORMATION REQUESTED 	INFORMATION REQUESTED 	250.0 				05-JUL-11 			NaN 			NaN 		NaN 		SA17A 		749073
3 	C00410118 	P20002978 	Bachmann, Michelle 	BLEVINS, DARONDA 	PIGGOTT 			AR 				7.24548e+08 	NONE 					RETIRED 				250.0 				01-AUG-11 			NaN 			NaN 		NaN 		SA17A 		749073
4 	C00410118 	P20002978 	Bachmann, Michelle 	WARDENBURG, HAROLD 	HOT SPRINGS NATION 	AR 				7.19016e+08 	NONE 					RETIRED 				300.0 				20-JUN-11 			NaN 			NaN 		NaN 		SA17A 		736166
'''
3.3.2 查看是否存在缺失数据
df.info()
'''
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 536041 entries, 0 to 536040
Data columns (total 16 columns):
 #   Column             Non-Null Count   Dtype  
---  ------             --------------   -----  
 0   cmte_id            536041 non-null  object 
 1   cand_id            536041 non-null  object 
 2   cand_nm            536041 non-null  object 
 3   contbr_nm          536041 non-null  object 
 4   contbr_city        536026 non-null  object 
 5   contbr_st          536040 non-null  object 
 6   contbr_zip         535973 non-null  object 
 7   contbr_employer    525088 non-null  object 
 8   contbr_occupation  530520 non-null  object 
 9   contb_receipt_amt  536041 non-null  float64
 10  contb_receipt_dt   536041 non-null  object 
 11  receipt_desc       8479 non-null    object 
 12  memo_cd            49718 non-null   object 
 13  memo_text          52740 non-null   object 
 14  form_tp            536041 non-null  object 
 15  file_num           536041 non-null  int64  
dtypes: float64(1), int64(1), object(14)
memory usage: 65.4+ MB
'''
3.3.3 统计描述
df.describe()
'''
 		contb_receipt_amt 	file_num
count 	5.360410e+05 		536041.000000
mean 	3.750373e+02 		761472.107800
std 	3.564436e+03 		5148.893508
min 	-3.080000e+04 		723511.000000
25% 	5.000000e+01 		756218.000000
50% 	1.000000e+02 		763233.000000
75% 	2.500000e+02 		763621.000000
max 	1.944042e+06 		767394.000000
'''
3.4 处理缺失值和异常值
3.4.1 处理缺失值

将缺失值填充为NOT PROVIDE。

df.fillna(value='NOT PROVIDE', inplace=True)
3.4.2 处理异常值

将捐款金额小于0的数据删除。

df = df.loc[~(df['contb_receipt_amt'] <= 0)]
3.5 党派列
3.5.1 新建列party

候选人与所属党派对应关系字典。

party_dict = {
    'Bachmann, Michelle': 'Republican',
    'Romney, Mitt': 'Republican',
    'Obama, Barack': 'Democrat',
    "Roemer, Charles E. 'Buddy' III": 'Reform',
    'Pawlenty, Timothy': 'Republican',
    'Johnson, Gary Earl': 'Libertarian',
    'Paul, Ron': 'Republican',
    'Santorum, Rick': 'Republican',
    'Cain, Herman': 'Republican',
    'Gingrich, Newt': 'Republican',
    'McCotter, Thaddeus G': 'Republican',
    'Huntsman, Jon': 'Republican',
    'Perry, Rick': 'Republican'
}

新建列party,表示各个候选人所在党派。

df['party'] = df['cand_nm'].map(party_dict)
3.5.2 分析列party

查看party列中有哪些不同的元素。

df['party'].unique()  # array(['Republican', 'Democrat', 'Reform', 'Libertarian'], dtype=object)

统计party列中各个值出现的次数。

df['party'].value_counts()
'''
Democrat       289999
Republican     234300
Reform           5313
Libertarian       702
Name: party, dtype: int64
'''

查看各个党派收到的政治献金总额contb_receipt_amt。

df.groupby(by='party')['contb_receipt_amt'].sum()
'''
party
Democrat       8.259441e+07
Libertarian    4.132769e+05
Reform         3.429658e+05
Republican     1.251181e+08
Name: contb_receipt_amt, dtype: float64
'''

查看具体每天各个党派收到的政治献金总额contb_receipt_amt。

df.groupby(by=['contb_receipt_dt','party'])['contb_receipt_amt'].sum()
'''
contb_receipt_dt  party      
01-APR-11         Reform             50.00
                  Republican      12635.00
01-AUG-11         Democrat       182198.00
                  Libertarian      1000.00
                  Reform           1847.00
                                   ...    
31-MAY-11         Republican     313839.80
31-OCT-11         Democrat       216971.87
                  Libertarian      4250.00
                  Reform           3205.00
                  Republican     751542.36
Name: contb_receipt_amt, Length: 1183, dtype: float64
'''
3.6 日期格式转换

将表中日期格式转换为yyyy-mm-dd。

def transform_date(d):
    day, month, year = d.split('-')
    month = months[month]
    return '20' + year + '-' + str(month) + '-' + day

# df['contb_receipt_dt'].map(transform_date)
df['contb_receipt_dt'] = df['contb_receipt_dt'].apply(transform_date)
3.7 查看老兵主要的支持谁

查看老兵(捐献者职业为DISABLED VETERAN)主要支持谁,就是看给谁捐的钱最多。

# 老兵对应的行数据
veteran_df = df.loc[df['contbr_occupation'] == 'DISABLED VETERAN']
# 根据候选人分组
veteran_df.groupby(by='cand_nm')['contb_receipt_amt'].sum()
'''
cand_nm
Cain, Herman       300.00
Obama, Barack     4205.00
Paul, Ron         2425.49
Santorum, Rick     250.00
Name: contb_receipt_amt, dtype: float64
'''

可以看出,候选人Obama, Barack获得老兵的捐赠最多,因此老兵主要支持Obama, Barack。

4 matplotlib

4.1 介绍

Matplotlib是Python的数据绘图包,可以与NumPy配合使用。

基本绘图流程

  1. 创建figure画布对象;
  2. 根据figure对象进行布局设置;
    figure对象(画布)上可以有多个作图区域,即axes坐标系。
  3. 获取对应位置的axes坐标系对象;
  4. 调用axes对象,在对应位置进行图形绘制;
    传入数据进行绘图,并设置图形细节。
  5. 显示图形 plt.show(),保存图形 fig.savefig('./demo.png')

导入包

import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline 

Jupyter Notebook中,魔法指令%matplotlib inline可以让绘制出来的图例展示在当前文件中,inline表示将图表嵌入到文件中。

4.2 条线图
4.2.1 单条线图
x = np.array([1, 2, 3, 4, 5])
y = x + 2
plt.plot(x, y)

在这里插入图片描述

4.2.2 多条线图
x = np.arange(1, 11)
y = x + 2
# 在一个坐标系中绘制多条线。
plt.plot(x, y)
plt.plot(x - 2, y + 3)
# 坐标系设置
plt.xlabel('x axis')
plt.ylabel('y axis')
plt.title('Matplotlib Demo')

在这里插入图片描述

4.3 图片显示设置
4.3.1 修改坐标系的显示比例
x = np.arange(1, 11)
y = x + 2
# 在绘图操作之前设置坐标系的显示比例
# 坐标的刻度不会发生改变。
plt.figure(figsize=(5, 2))
# 在一个坐标系中绘制多条线。
plt.plot(x, y)
plt.plot(x - 2, y + 3)
# 坐标系设置
plt.xlabel('x axis')
plt.ylabel('y axis')
plt.title('Matplotlib Demo')

在这里插入图片描述

4.3.2 设置图例
x = np.arange(1, 11)
y = x + 2
# 设置图例
plt.plot(x, y, label='Line 1')
plt.plot(x - 2, y + 3, label='Line 2')
plt.legend()
# 坐标系设置
plt.xlabel('x axis')
plt.ylabel('y axis')
plt.title('Matplotlib Demo')

在这里插入图片描述

4.3.3 保存图片
# 1. 生成figure对象
fig = plt.figure()
# 2. 绘图
x = np.array([1, 2, 3, 4, 5])
y = x + 2
plt.plot(x, y)
# 3. 显示图片
plt.show()
# 4. 保存图片
plt.savefig('./demo.png')
4.4 其它类型图表绘制
4.4.1 柱状图 plt.bar
bar(x, height, width=0.8...)

x:索引;
height:柱高,即数据值;
width:条形宽度。

x_list = [1, 2, 3, 4, 5]
height_list = [3, 8, 5, 7, 6] 
plt.bar(x_list, height=height_list, width=0.5)

在这里插入图片描述

4.4.2 直方图(密度图) plt.hist
plt.hist(x, bins=None, normed=None, orientation='vertical', color=None...)

bins:指定条形数量的整数值;
normed:是否进行归一化处理,即形成概率密度,默认值为False;
orientation:指定直方图的方向,horizontal表示水平,vertical表示垂直(默认);
color:指定直方图的颜色,可以是颜色值或颜色序列。

x = [1, 1, 1, 1, 2, 3, 3, 3, 4, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 8, 9]
plt.hist(x, bins=20)
'''
(array([4., 0., 1., 0., 0., 3., 0., 1., 0., 0., 2., 0., 7., 0., 0., 1., 0.,
        1., 0., 1.]),
 array([1. , 1.4, 1.8, 2.2, 2.6, 3. , 3.4, 3.8, 4.2, 4.6, 5. , 5.4, 5.8,
        6.2, 6.6, 7. , 7.4, 7.8, 8.2, 8.6, 9. ]),
 <a list of 20 Patch objects>)
'''
'''
返回值解读:1至1.4之间柱子高度为4,1.4至1.8之间柱子高度为0,...
'''

在这里插入图片描述

x = [1, 1, 1, 1, 2, 3, 3, 3, 4, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 8, 9]
plt.hist(x, bins=20, normed=True, orientation='horizontal', color='r')
'''
(array([0.47619048, 0.        , 0.11904762, 0.        , 0.        ,
        0.35714286, 0.        , 0.11904762, 0.        , 0.        ,
        0.23809524, 0.        , 0.83333333, 0.        , 0.        ,
        0.11904762, 0.        , 0.11904762, 0.        , 0.11904762]),
 array([1. , 1.4, 1.8, 2.2, 2.6, 3. , 3.4, 3.8, 4.2, 4.6, 5. , 5.4, 5.8,
        6.2, 6.6, 7. , 7.4, 7.8, 8.2, 8.6, 9. ]),
 <a list of 20 Patch objects>)
'''

在这里插入图片描述

4.4.3 散点图 plt.scatter
x = np.linspace(-np.pi, np.pi, num=20)
y = np.random.randint(0, 20, size=(20,))
plt.scatter(x, y)

在这里插入图片描述

4.4.4 饼图 plt.pie
plt.pie(x,...)
arr=[11, 22, 31, 15]
plt.pie(arr)

在这里插入图片描述

arr=[0.2, 0.3, 0.1]
plt.pie(arr)

在这里插入图片描述

arr = [11, 22, 31, 15]
plt.pie(arr, labels=['a', 'b', 'c', 'd'])

在这里插入图片描述

arr = [11, 22, 31, 15]
plt.pie(arr, labels=['a', 'b', 'c', 'd'], labeldistance=0.3)

在这里插入图片描述

arr = [11, 22, 31, 15]
plt.pie(arr, labels=['a', 'b', 'c', 'd'], labeldistance=0.3, autopct='%.6f%%')

在这里插入图片描述

arr = [11, 22, 31, 15]
plt.pie(arr, labels=['a', 'b', 'c', 'd'], labeldistance=0.3, shadow=True, explode=[0.2, 0.3, 0.2, 0.4])

在这里插入图片描述

  • 4
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我了解了。对于你的问题,我可以给你一个简单的数据分析与可视化案例,使用PythonPandasMatplotlib库。 首先,我们需要准备一个数据集。这里我选用了一个名为“tips”的数据集,它记录了一家餐厅的不同顾客在用餐时的消费金额、小费、性别、是否吸烟、用餐时间等信息。你可以在Seaborn库中找到这个数据集。 接下来,我们可以使用Pandas库将数据集导入到Python中,并进行一些简单的数据处理。例如,我们可以计算不同性别的平均小费金额: ```python import pandas as pd # 导入数据集 tips = pd.read_csv("https://raw.githubusercontent.com/mwaskom/seaborn-data/master/tips.csv") # 计算不同性别的平均小费金额 tips.groupby("sex")["tip"].mean() ``` 结果如下: ``` sex Female 2.833448 Male 3.089618 Name: tip, dtype: float64 ``` 接下来,我们可以使用Matplotlib库将这些数据可视化。例如,我们可以绘制不同性别的平均小费金额柱状图: ```python import matplotlib.pyplot as plt # 绘制不同性别的平均小费金额柱状图 tips.groupby("sex")["tip"].mean().plot(kind="bar") # 设置图形标题和坐标轴标签 plt.title("Average Tip by Gender") plt.xlabel("Gender") plt.ylabel("Tip") # 显示图形 plt.show() ``` 结果如下: ![Average Tip by Gender](https://i.imgur.com/5XjVwUH.png) 这只是一个简单的数据分析与可视化案例,你可以根据自己的需求和数据集进行更复杂的数据分析和可视化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值