最近遇到一个需求,遍历一个大小为几十G的文件夹下面所有的CSV文件的列名,将列名全部抽取出来写入新的CSV文件中,并设置每个文件中是否存在该列名,若存在则设置为1,否则设置为0。
其中输入进行遍历操作的CSV文件没有什么特别的要求,只要符合第一行为列名,其余为数据即可。如下
要求输出的文件格式如下:
首先,我们需要遍历该folder下面的所有CSV文件,并获取其路径名。
其次我们打开每个csv文件,获取第一行列名,并对第一个读取的文件进行特殊处理,即第一个文件的所有列名写入到新的dataframe中,值都设置为1。之后遍历的所有的文件列名都与上一次的dataframe列名进行对比,若列名不存在,则添加该列名,再遍历添加之后的列名,不存在则该文件下的列名的值设置为0, 否则设置为1。
最后将返回的datafram写入csv文件中。具体代码如下:
# -*- coding:utf8 -*-
import os
import pandas as pd
import time
def extract_columns_from_csv():
path_dir = "D:\\电产数据整理-0917"
new_pd = pd.DataFrame()
# 存放该目录包括子目录底下的所有的csv文件
csv_list = []
# 遍历该文件夹包括子文件下所有CSV文件
for root, dirs, files in os.walk(path_dir, topdown=True):
for name in dirs:
file_name = os.path.join(root, name)
if os.path.splitext(file_name)[-1] == '.csv':
csv_list.append(file_name)
for name in files:
file_name = os.path.join(root, name)
if os.path.splitext(file_name)[-1] == '.csv':
csv_list.append(file_name)
# 遍历每个csv文件,提取列名,注意,用pandas.read_csv的方式特别慢,此处不需要全部读入数据,只需要读取第一行数据。
column_list = []
for info in csv_list:
with open(info, 'r') as f:
j = 0
for line in f:
if j < 1:
column_list = line.strip().split(",")
break
j = j + 1
# 获取每个文件的实验种类
csv_type = info.split("\\")[4]
# 读取第一个文件
if len(new_pd) == 0:
header = column_list
header.insert(0, "文件名")
header.insert(1, "实验种类")
value_list = [1 for _ in range(len(header)-2)]
value_list.insert(0, info)
value_list.insert(1, csv_type)
new_pd = pd.DataFrame(columns=header)
new_pd.loc[len(new_pd)] = value_list
else:
value_list = []
# 取出每个文件的列名,判断是否存在于上次已经记录好的header中,若不存在,在header末尾增加该列名,该文件名下的标记为0,否则为1
for each in column_list:
if each not in header:
header.append(each)
for _ in header[2:]:
if _ not in column_list:
value_list.append(0)
else:
value_list.append(1)
value_list.insert(0, info)
value_list.insert(1, csv_type)
new_pd = new_pd.reindex(columns=header, fill_value=0)
new_pd.loc[len(new_pd)] = value_list
return new_pd
# 保存到CSV文件中
if __name__ == "__main__":
time1 = time.time()
new_pd = extract_columns_from_csv()
new_pd.to_csv('data/columns_extracted_all.csv', index=False)
print(time.time()-time1) # 292.88509464263916
```