pandas统计各个城市的平均房价
上一次使用scrapy框架爬取到全国房价,今天我便想使用pandas来统计出陕西省各个城市的房价并利用matplotlib进行数据展示。
首先,在pandas模块中提供了很方便地从mysql数据库中读取数据,方法如下:
def __init__(self):
'''从数据库读取房价信息'''
self.conn = pymysql.connect(host = 'localhost',
user = 'root',
passwd = 'root',
db = 'fang',
charset = 'utf8')
sql_query = 'select * from fang.fang_info'
self.df = pd.read_sql(sql_query, con=self.conn)
# print(df.head(10))
# print(df.info())
读取到数据后按照name属性进行数据的去重:df_shanxi_info = df_shanxi.drop_duplicates('name')
分析数据:由于只需要统计平均房价,所以读取到的房源信息中只需要关注‘price’这一列,其它的不做考虑。而在‘price’中有这几种:4100元/㎡、价格待定往期3800元/㎡、价格待定、价格待定周边6066元/㎡、259万元/套等且都是字符串。
1. 由于259万元/套类型的房子很少且对整个的数据分析结果不会造成大的影响,所以有/套的行可以舍去。pandas中提供了一种方法isin():isin()接受一个列表,判断该列中元素是否在列表中,反函数就是在前面加上 ~。示例代码如下:
# 取出所有不包含'/套'的数据
df_shanxi_info = df_shanxi_info[~(df_shanxi_info['price'].map(lambda x:x.split('/')[-1]).isin(['套']))]
2.对于其它的,由于是字符串,所以不能对其进行求平均值,而且其含有中文和其他符号,所以也不能对其强制类型转换。解决方法:
- 可以使用replace函数进行过滤:
df.replace(to_replace, value)
前面是需要替换的值,后面是替换后的值。对于多个条件可以写为:df.replace(to_replace, value).replace(to_replace, value).replace(to_replace, value).replace(to_replace, value)
。
但是由于price中需要替换的元素太多而且不确定,所以在这里我使用了另外一种方式,也是十分方便的方法----->正则表达式 - str.extract(),可用正则从字符数据中抽取匹配的数据,只返回第一个匹配的数据。
str.extract(pat, flags=0, expand=None)
参数: pat : 字符串或正则表达式 flags : 整型, expand : 布尔型,是否返回DataFrame 。示例代码如下:
# 只提取价格中的数字 3000元/㎡------->3000
self.df['price_num'] = df_shanxi_info['price'].str.extract(r'(\d+)', flags=0, expand=False).astype('float64')
- 在提取到price中想要的数据后便可以将其与原来的数据进行合并:
join:默认情况下把行索引相同的数据合并到一起,例如:
- 完成之后数据中会有NaN数据,进行处理:
df_shanxi_info = df_shanxi_info[pd.notnull(self.df['price_num'])]
- 然后按照城市分组求每个城市的平均价格:
# 按照城市分组求每个城市的平均价格
shanxi_grouped = self.df['price_num'].groupby(df_shanxi_info['city']).mean().sort_values(ascending=False)
得到的是一个 **‘pandas.core.series.Series’**类型的数据
- 至此,数据的清洗、过滤等工作已经完成,为了更好地呈现出数据,我利用了python中的matplotlib模块进行绘图展示:如下:
fig = plt.figure(figsize=(20, 8), dpi=80)
my_font = font_manager.FontProperties(fname="C:/WINDOWS/FONTS/SIMHEI.TTF", size=20)
text_font = font_manager.FontProperties(fname="C:/WINDOWS/FONTS/MSYHL.TTC", size=50)
_x = range(len(shanxi_grouped.index))
_y = shanxi_grouped.values
plt.bar(_x, _y, width=0.2, color='blue')
plt.xticks(_x, shanxi_grouped.index, fontproperties=my_font, size=13)
plt.xlabel('城市', fontproperties=my_font, color='orange')
plt.ylabel('平均房价(元/㎡)', fontproperties=my_font, color='orange')
plt.title('陕西省各个城市的平均房价统计', fontproperties=my_font, color='orange')
程序完整代码:
import pymysql
import pandas as pd
from matplotlib import pyplot as plt
from matplotlib import font_manager
class Fang():
def __init__(self):
'''从数据库读取房价信息'''
self.conn = pymysql.connect(host = 'localhost',
user = 'root',
passwd = 'root',
db = 'fang',
charset = 'utf8')
sql_query = 'select * from fang.fang_info'
self.df = pd.read_sql(sql_query, con=self.conn)
# print(df.head(10))
# print(df.info())
def extract_shanxi(self):
'''选取陕西省的房价信息'''
df_shanxi = self.df[(self.df['province'] == '陕西')]
# 去掉重复信息
df_shanxi_info = df_shanxi.drop_duplicates('name')
# 取出所有不包含'/套'的数据
df_shanxi_info = df_shanxi_info[~(df_shanxi_info['price'].map(lambda x:x.split('/')[-1]).isin(['套']))]
# 只提取价格中的数字 3000元/㎡------->3000并与之前的数据合并
self.df['price_num'] = df_shanxi_info['price'].str.extract(r'(\d+)', flags=0, expand=False).astype('float64')
df_shanxi_info = df_shanxi_info.join(self.df['price_num'])
df_shanxi_info = df_shanxi_info[pd.notnull(self.df['price_num'])]
# 按照城市分组求每个城市的平均价格
shanxi_grouped = self.df['price_num'].groupby(df_shanxi_info['city']).mean().sort_values(ascending=False)
print(type(shanxi_grouped))
self.conn.close()
return shanxi_grouped
def draw_fang(self, shanxi_grouped):
'''画图'''
fig = plt.figure(figsize=(20, 8), dpi=80)
my_font = font_manager.FontProperties(fname="C:/WINDOWS/FONTS/SIMHEI.TTF", size=20)
text_font = font_manager.FontProperties(fname="C:/WINDOWS/FONTS/MSYHL.TTC", size=50)
_x = range(len(shanxi_grouped.index))
_y = shanxi_grouped.values
plt.bar(_x, _y, width=0.2, color='blue')
plt.xticks(_x, shanxi_grouped.index, fontproperties=my_font, size=13)
plt.xlabel('城市', fontproperties=my_font, color='orange')
plt.ylabel('平均房价(元/㎡)', fontproperties=my_font, color='orange')
plt.title('陕西省各个城市的平均房价统计', fontproperties=my_font, color='orange')
# 网格
plt.grid(linestyle="--", alpha=0.4)
# 水印
fig.text(x=0.4,
y=0.7,
s='好吃的小西红柿',
color='gray',
fontproperties=text_font,
rotation=45,
alpha=0.2)
plt.savefig('./fang.png')
plt.show()
def run(self):
shanxi_grouped = self.extract_shanxi()
self.draw_fang(shanxi_grouped)
if __name__ == '__main__':
fang = Fang()
fang.run()
数据展示: