数据分析——火车信息

任务目标

任务

1、整理火车发车信息数据,结果的表格形式为:

数据分析——火车信息_第1张图片

2、并输出最终的发车信息表

难点

1、多文件

        一个文件夹,多个月的发车信息,一个excel,放一天的发车情况

2、数据表的格式特殊

        如何分析表是一个难点

数据形式

图像呈现

数据分析——火车信息_第2张图片

数据分析——火车信息_第3张图片

数据分析——火车信息_第4张图片

数据分析——火车信息_第5张图片

文字描述

1、一张表含多辆车次信息

2、一辆车次信息分为标题(日期、车次、定员、客座率)和表格信息部分

3、表格信息部分分为x,y轴看

        横着是发车站点、发车时间、下车人数

        竖着是目标站点、到达时间、上车人数

4、图标呈现下三角趋势,因为过站无上车人数

注意:

        因为横着是上车站点,终点站没有人上车,所以横着的车次不包含终点站,是所有车次-1

        竖着的车次包含终点站——即所有车次信息

分析步骤

1、导入数据

数据分析——火车信息_第6张图片

数据分析——火车信息_第7张图片

存在问题

与原数据不同,原数据中的表头在该表的第一列中,每个属性对应的行为空值

处理方法

处理结果

数据分析——火车信息_第8张图片

结果分析

1、38列

        因为原excel表中,有车次信息到第38列,导入数据会保持表格格式完整性,所以取最大列数

        不到38的列数均为空值,需要处理

2、表格信息被存放在第一行中,还需处理

3、目标需求信息只到29列的下车人数,所以需要把有效信息抠出来

语法扩展(别人的资料)

python中pandas包使用的一个header参数_header=none-CSDN博客

数据分析——火车信息_第9张图片

数据分析——火车信息_第10张图片

数据分析——火车信息_第11张图片

2、数据处理

        2.1获取有效信息(扣表)

                2.1.1思路分析
                        1、判断车次

                              整张表包含很多车次

                              要知道哪一辆车是第几行到第几行,需要拆分

                            (即怎么判断,eg:0-33为车1,34-45为车2,······)

数据分析——火车信息_第12张图片

                         2、处理表头

                             导入的表中有很多表头,需要处理 ,把所有车次的表头抽取出来,找共同点

                             都有客座率

数据分析——火车信息_第13张图片

数据分析——火车信息_第14张图片

                        2.1.2解决方案
                                1、找表头

                                      1.1data[0] 

                                         因为数据表行列均有属性,表头均在第0列,所以先判断data[0]是第0行还是第0列

数据分析——火车信息_第15张图片

                                        1.2找到含有“客座率”的行数

数据分析——火车信息_第16张图片

语法扩展
apply()、lambda

数据分析——火车信息_第17张图片

loc()

Pandas读取某列、某行数据——loc、iloc用法总结_pandas读取某一行的数据-CSDN博客

数据分析——火车信息_第18张图片

                                1.3生成由表头信息组成的表

数据分析——火车信息_第19张图片

                                1.4批量分割+展开表

按照空格分割后得到一个表格

数据分析——火车信息_第20张图片

split()

Python知识精解:str split()方法 - 知乎 (zhihu.com)

expand参数

pandas的分列操作str.split()_pandas数据分列-CSDN博客

数据分析——火车信息_第21张图片

                                  2、生成除表头外的信息表

data=data[~ind]

数据分析——火车信息_第22张图片

                                 3、生成一趟车的数据

1、根据上车站点和上车人数所在的行(用遍历匹配)

确定每一趟列车所包含的行数,再扣其中的数据

数据分析——火车信息_第23张图片2、找第一趟车的信息

数据分析——火车信息_第24张图片

3、重置行索引

因为之前删数据把行索引删了,出现了数据缺失,需要重置行索引

数据分析——火车信息_第25张图片

数据分析——火车信息_第26张图片

drop——删除多余的一列index

4、删除空值

重置索引后的表格为

数据分析——火车信息_第27张图片

表中30列后的值均为空值,需要删除

用空值数量进行判断,若某一列中空值数量=行数,则证明该列全为空,需要删除

数据分析——火车信息_第28张图片

5、生成完整一趟车的信息表

数据分析——火车信息_第29张图片

语法扩展
loc、iloc区别

pandas索引函数loc和iloc的区别_pandas loc与iloc区别-CSDN博客

loc基于标签索引、iloc基于位置索引

reset_index()

如何在pandas中使用set_index( )与reset_index( )设置索引 - 知乎 (zhihu.com)

3、数据分析

处理后的表

数据分析——火车信息_第30张图片

3.1取表头信息表中所需数据

数据分析——火车信息_第31张图片

数据分析——火车信息_第32张图片

3.2把表头信息与每辆车挂钩

原数据(2个表)

表头表

数据分析——火车信息_第33张图片

车次表

数据分析——火车信息_第34张图片

通过索引和步长取出需要的信息行

数据分析——火车信息_第35张图片

这样就匹配成功了

3.3、取所有站点

数据分析——火车信息_第36张图片

3.4循环所有站点取数据(用定位)

数据分析——火车信息_第37张图片

都用条件筛选

数据分析——火车信息_第38张图片

3.5整体操作(合并前面操作)

数据分析——火车信息_第39张图片

语法扩展

python dataframe是什么_Pandas 库之 DataFrame-CSDN博客

4、封装函数

数据分析——火车信息_第40张图片

5、数据导出

数据分析——火车信息_第41张图片

数据分析——火车信息_第42张图片

数据分析——火车信息_第43张图片

语法扩展
glob——查找文件

Python标准库glob模块详解_python glob-CSDN博客

tpdm——进度条

【python第三方库】tqdm简介_python tqdm库-CSDN博客

enumerate() 函数

Python enumerate() 函数 | 菜鸟教程

to_csv()

pandas的to_csv()使用方法_pandas to_csv-CSDN博客

总体代码

import warnings
warnings.filterwarnings('ignore')
import pandas as pd

path = './201501-201603/201501/20150101.xls'
data = pd.read_excel(path, skiprows=2, header=None)
data.head(50)

# 日期
dates = path.split('/')[-1][:8]

ind = data[0].apply(lambda x: '客座率' in x) # 筛选有车次信息的行数据
car_info = data.loc[ind, 0]
car_info = car_info.str.split(' ', expand=True) # 这里的得到车次、定员、客座率

car_info

# 删除车次信息行
data = data[~ind]
data.reset_index(inplace=True, drop=True)
data.head()

## 接下来:找到某一趟车所在的小表格,思路就是找到【上车站、上车人数合计】所在的行
ind = data[0].apply(lambda x: '上车站'==x or '上车人数合计'==x)
car_index = data[ind]

all_car = pd.DataFrame()
for start, end, checi, dingyuan, kezuolv in zip(car_index.index[0::2],car_index.index[1::2], car_info[0], car_info[6], car_info[8]):
    one_car = data.iloc[start:end+1, :] # 截取其中一趟车的数据
    one_car.reset_index(inplace=True, drop=True) # 重置索引
    col_ind = one_car.isna().sum(axis=0)==len(one_car) # 判断全为空的列
    one_car = one_car.loc[:, ~col_ind] # 删除空列
    station = one_car.iloc[2:-1, 0] # 取所有站点,在2至倒数第一行
    one_car_list = []
    for s in station: # 循环每个站点去取数据
        one_car_dict = {}
        one_car_dict['车次'] = checi
        one_car_dict['定员'] = dingyuan
        one_car_dict['客座率'] = kezuolv
        one_car_dict['日期'] = dates
        one_car_dict['站点'] = s
        one_car_dict['进站时间'] = one_car.loc[one_car[0]==s, 1].values[0] # 进站时间
        one_car_dict['下车人数'] = one_car.loc[one_car[0]==s, one_car.shape[1]-1].values[0] # 下车人数
        try:
            one_car_dict['离站时间'] = one_car.loc[1,one_car.iloc[0]==s].values[0] # 离站时间
            one_car_dict['上车人数'] = one_car.loc[len(one_car)-1,one_car.iloc[0]==s].values[0] # 上车人数
        except:
            one_car_dict['离站时间'] = '--' # 终点站没有出站时间和人数
            one_car_dict['上车人数'] = '--'
        one_car_list.append(one_car_dict)
    one_car_data = pd.DataFrame(one_car_list)
    break
    #all_car = pd.concat([all_car, one_car_data])
#这一步结束就能看到处理后表的信息了
    one_car_data

def get_one_file(path):
    data = pd.read_excel(path, skiprows=2, header=None) # 读数据
    dates = path.split('/')[-1][:8] # 日期
    ind = data[0].apply(lambda x: '客座率' in x) # 筛选有车次信息的行数据
    car_info = data.loc[ind, 0]
    car_info = car_info.str.split(' ', expand=True) # 这里的得到车次、定员、客座率
    data = data[~ind] # 删除车次信息行
    data.reset_index(inplace=True, drop=True)
    ## 接下来:找到某一趟车所在的小表格,思路就是找到【上车站、上车人数合计】所在的行
    ind = data[0].apply(lambda x: '上车站'==x or '上车人数合计'==x)
    car_index = data[ind]
    all_car = pd.DataFrame()
    for start, end, checi, dingyuan, kezuolv in zip(car_index.index[0::2],car_index.index[1::2], car_info[0], car_info[6], car_info[8]):
        one_car = data.iloc[start:end+1, :] # 截取其中一趟车的数据
        one_car.reset_index(inplace=True, drop=True) # 重置索引
        col_ind = one_car.isna().sum(axis=0)==len(one_car) # 判断全为空的列
        one_car = one_car.loc[:, ~col_ind] # 删除空列
        station = one_car.iloc[2:-1, 0] # 取所有站点,在2至倒数第一行
        one_car_list = []
        for s in station: # 循环每个站点去取数据
            one_car_dict = {}
            one_car_dict['车次'] = checi
            one_car_dict['定员'] = dingyuan
            one_car_dict['客座率'] = kezuolv
            one_car_dict['日期'] = dates
            one_car_dict['站点'] = s
            one_car_dict['进站时间'] = one_car.loc[one_car[0]==s, 1].values[0] # 进站时间
            one_car_dict['下车人数'] = one_car.loc[one_car[0]==s, one_car.shape[1]-1].values[0] # 下车人数
            try:
                one_car_dict['离站时间'] = one_car.loc[1,one_car.iloc[0]==s].values[0] # 离站时间
                one_car_dict['上车人数'] = one_car.loc[len(one_car)-1,one_car.iloc[0]==s].values[0] # 上车人数
            except:
                one_car_dict['离站时间'] = '--' # 终点站没有出站时间和人数
                one_car_dict['上车人数'] = '--'
            one_car_list.append(one_car_dict)
        one_car_data = pd.DataFrame(one_car_list)
        all_car = pd.concat([all_car, one_car_data])
    return all_car

from glob import glob
from tqdm import tqdm
all_path = glob('./201501-201603/*/*')
for i,path in tqdm(enumerate(all_path)):
    data = get_one_file(path)
    if i==0:
        data.to_csv('./result.csv', header=True, index=None, encoding='utf8', mode='a')
    else:
        data.to_csv('./result.csv', header=None, index=None, encoding='utf8', mode='a')

你可能感兴趣的:(python,数据分析,数据分析,数据挖掘,python,pandas)