7-Python数据处理-小记

7-Python数据处理-小记

本文涉及的内容有:

numpypandas的简单应用

python排列组合

python进度条的简单使用

1.1本文背景

本文的需求用以下示例说明。

  1. 原始数据如下图所示,多行多列,每行的列数不一定相同

在这里插入图片描述

  1. 针对每一行,按照排列组合的方式,将该行转行成多行两列的数据。例如上图中的第2行为1,2,3,所有的组合情况为(1,2),(1,3),(2,3)。则转换之后的数据就是下图所示的样子。

在这里插入图片描述

  1. 每一行都处理成上图的样子,合在一起,在第一行再加一个标签行,就得到了最终的结果。

1.2关于CSV格式

原始数据格式是.xlsx格式,为了方便,我先转换成了.csv格式。发现:

  • 原始数据有多列,每一行的列数不固定,有多有少
  • 转换成.csv格式(用逗号分隔)之后,每一行的列数被固定下来,统一长度为最大列数
  • 转换之后的数据如下图所示。

在这里插入图片描述

1.3计算每一行数据的有效长度

1.2可知,用python读取进来的csv格式的数据中,有些列的元素是空的,而我们需要处理的数据是每一行的非空元素。所以需要计算每一行的有效数据长度。因此对于整个数据data中的每一行数据data_item,有如下步骤(非空元素只会从左边开始出现,并且是连续的):

  1. 获取所有空值即''的下标位置,这些下标位置存放在一个数组length当中
  2. 如果length非空(说明这一行的有效元素的个数小于最大列数),则获取最后一个有效元素的下一个位置的下标位置position_last
  3. 如果length空(说明原数据有效长度等于最大列数),同样的,获取最后一个有效元素的下一个位置的下标位置
  4. 需要注意的是,如果position_last==1(说明这一行数据只有一列),需要剔除掉,即不需要进行之后的处理,直接处理下一行
  5. 这一过程的代码如下所示。
# 1.1计算每一行数据的有效长度
length = np.argwhere(data_item == '')  # 返回所有满足条件的元素的下标位置
# print("length:", length)
if len(length) > 0:
    # 有效长度小于最大列数
    # 获取最后一个有效元素的下一个位置的下标位置
    position_last = length[0][0]
    # print(position_last)
else:
    # 说明原数据有效长度等于最大列数
    # 获取最后一个有效元素的下一个位置的下标位置
    position_last = len(data_item)
# print("position_last:", position_last)
if position_last == 1:
    # 说明这一行数据只有一列,需要剔除掉,即不需要进行之后的处理,直接跳过
    continue

1.4计算所有的组合情况

  • 这里用到了combinations函数。第一个参数是一个可迭代对象,第二个参数是每个组合的元素个数。使用list()函数将combinations函数的返回值变成列表,列表的每个元素是一个二元组。
  • 1.3也说了,有效元素只会出现在每一行的左边,因此接下来需要对左边的元素的可能组合情况进行计算;
  • 这里选择对元素的下标进行组合计算,之后再通过下标进行遍历即可。
  • 计算组合的代码如下。
from itertools import combinations
# 1.2计算所有的组合情况
combinations_list = list(combinations(np.arange(0, position_last), 2))
# print("combinations_list:", combinations_list)
  • 遍历刚刚计算得到的二元组列表,即可得到这一行数据的所有组合情况
# 1.3遍历所有组合情况,取得对应的两列数据
for combination in combinations_list:
    final_data.append([data_item[combination[0]], data_item[combination[1]]])
  • 所有数据处理完成之后,得到的final_data是一个列表,其元素是一个二元列表,在输出到文件之前还需要进行一些处理。

1.5转换成DataFrame

  1. 为了方便写入文件,选择将final_data列表转换成DataFrame格式。转换方式如下所示。
# 2.1定义列名
names = ['id1', 'id2']
# 2.2转换成DataFrame格式,方便写入csv文件
pd_data = pd.DataFrame(columns=names, data=final_data)
# print('pd_data:\n', pd_data)
  1. 由于数据处理的需要,我发现当前处理好的数据中存在有些航,其两列的元素值完全一样,对于我是没有用的,需要将这样的行删除掉。
    1. 首先获取需要删除的行的行索引值
    2. 再使用drop函数一起删除掉
    3. 这一过程还是用了进度条功能(导入tqdm包,并将迭代对象放入tqdm()函数中即可)
    4. 代码如下所示。
print("正在删除不符合条件的数据...")
time.sleep(2)
# 2.3由于数据中存在某些行,其两列元素是完全一样的,因此增加了剔除这样的行的步骤
index_list = []  # 存放需要剔除掉的数据所在的行号
with tqdm(total=pd_data.shape[0]) as pbar:
    for index, row in pd_data.iterrows():
        # 按行遍历,将DataFrame的每一行迭代为(index, Series)
        # 对于每一行,通过列名name访问对应的元素
        if row['id1'] == row['id2']:
            # 两列元素是完全一样的
            index_list.append(index)
        pbar.update(1)

# print("index_list:", index_list)
pd_data = pd_data.drop(index=index_list)
# print('pd_data:\n', pd_data)
  1. 最后写入文件即可
# 2.4写入文件
print("正在写入文件...")
pd_data.to_csv("data_processed.csv", encoding='utf8', index=False)  # 不保留行索引

1.6完整代码

数据可参照本文讲述内容自行设置。

import numpy as np
from itertools import combinations
from tqdm import tqdm
import pandas as pd
import time

data = np.loadtxt("data.csv", delimiter=',', encoding='utf-8', dtype=str)
# print(data)
final_data = []  # 存放处理之后的数据
print("正在分隔数据...")
# 1、遍历每一行数据
for data_item in tqdm(data):
    position_last = 0
    combinations_list = []
    # print("data_item:", data_item)
    # print(type(data_item))
    # 1.1计算每一行数据的有效长度
    length = np.argwhere(data_item == '')  # 返回所有满足条件的元素的下标位置
    # print("length:", length)
    if len(length) > 0:
        # 有效长度小于最大列数
        # 获取最后一个有效元素的下一个位置的下标位置
        position_last = length[0][0]
        # print(position_last)
    else:
        # 说明原数据有效长度等于最大列数
        # 获取最后一个有效元素的下一个位置的下标位置
        position_last = len(data_item)
    # print("position_last:", position_last)
    if position_last == 1:
        # 说明这一行数据只有一列,需要剔除掉,即不需要进行之后的处理,直接跳过
        continue
    # 1.2计算所有的组合情况
    combinations_list = list(combinations(np.arange(0, position_last), 2))
    # print("combinations_list:", combinations_list)
    # 1.3遍历所有组合情况,取得对应的两列数据
    for combination in combinations_list:
        final_data.append([data_item[combination[0]], data_item[combination[1]]])
time.sleep(2)
print("正在转换格式...")
# print("final_data:", final_data)
# print(type(final_data))
# 2、将数据写入csv文件
# 2.1定义列名
names = ['id1', 'id2']
# 2.2转换成DataFrame格式,方便写入csv文件
pd_data = pd.DataFrame(columns=names, data=final_data)
# print('pd_data:\n', pd_data)
print("正在删除不符合条件的数据...")
time.sleep(2)
# 2.3由于数据中存在某些行,其两列元素是完全一样的,因此增加了剔除这样的行的步骤
index_list = []  # 存放需要剔除掉的数据所在的行号
with tqdm(total=pd_data.shape[0]) as pbar:
    for index, row in pd_data.iterrows():
        # 按行遍历,将DataFrame的每一行迭代为(index, Series)
        # 对于每一行,通过列名name访问对应的元素
        if row['id1'] == row['id2']:
            # 两列元素是完全一样的
            index_list.append(index)
        pbar.update(1)

# print("index_list:", index_list)
pd_data = pd_data.drop(index=index_list)
# print('pd_data:\n', pd_data)
# 2.4写入文件
print("正在写入文件...")
pd_data.to_csv("data_processed.csv", encoding='utf8', index=False)  # 不保留行索引
_list:", index_list)
pd_data = pd_data.drop(index=index_list)
# print('pd_data:\n', pd_data)
# 2.4写入文件
print("正在写入文件...")
pd_data.to_csv("data_processed.csv", encoding='utf8', index=False)  # 不保留行索引
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值