2016-04-23 1 views
1

У меня есть папка из 1000 CSV-файлов для определенных наборов данных. Для каждого набора данных у меня есть три типа данных. Именования выглядит следующим образом:pythonic style для фильтрации данных в csvs

(предполагается, что имя набора данных 'ааа')

  1. 'aaa_values.csv'
  2. 'aaa_info.csv'
  3. 'aaaps.csv'

Каждый набор данных имеет заголовок различной длины например, «aaa», «ab3fz», «gjt89» и т. д. Обратите внимание, что третий тип данных не имеет подчеркивания, разделяющего тип - это 'ps.csv'

Я хотел бы отфильтровать это, чтобы получить вселенную наборов данных. Мне удалось сделать это со следующим кодом Python, но он неуклюж и не очень «Pythonic».

Есть ли у кого-нибудь предложения для более элегантного способа сделать это?

import os 
x = [] 
y = os.listdir("C:\\Anaconda3\\Python_Library\\Python_Folder\\csvData") 
for i in y: 
    x.append(i.split('_')) 
h = [] 
for i in x: 
    for j in i: 
     h.append(j) 
c = [l for l in h if l != 'values.csv'] 
c = list(set([p for p in c if p != 'info.csv'])) 
[t for t in c if t[-6:]!='ps.csv'] 

ответ

1

Первым шагом к более Pythonic кода использует более описательные имена, чем x, y, i, j, c и p.Это выглядит немного лучше:

# paths = os.listdir("C:\\Anaconda3\\Python_Library\\Python_Folder\\csvData") 
paths = ['aaa_values.csv', 'aaa_info.csv', 'aaaps.csv', 'bbbps.csv', 'ccc_info.csv'] 
res = set() 
for path in paths: 
    path_parts = path.split('_') 
    last = path_parts[-1] 
    if (last == 'values.csv' or last == 'info.csv'): 
     res.add(path_parts[0]) 
    elif last[-6:] == 'ps.csv': 
     res.add(last[:-6]) 

Сейчас:

>>> res 
{'aaa', 'bbb', 'ccc'} 
0

Используйте набор для удаления дубликатов, а также использовать find() для проверки и найти '_' в имени файла:

import os 

path = "C:\\Anaconda3\\Python_Library\\Python_Folder\\csvData" 
suffixlength = len('ps.csv') 

# use a set to remove duplicates 
datasets = set() 

for filename in os.listdir(path): 

    # find() returns the index of the '_' or -1 if it isn't found. 
    i = filename.find('_') 

    # chop the filename at the index of the '_' if found else just 
    # before the 'ps.csv' suffix 
    datasets.add(filename[:i] if i>0 else filename[:-suffixlength]) 
0

Regular expressions и set comprehensions очень Pythonic, поэтому продлить на примере Майка Мюллера:

import re 
import os 

# see https://regex101.com/r/sR5cQ8 for the regex explanation 
dataset_re = re.compile(r'^(.*)(?:_values|_info|ps)\.csv$') 

# paths = os.listdir("C:\\Anaconda3\\Python_Library\\Python_Folder\\csvData") 
paths = ['aaa_values.csv', 'aaa_info.csv', 'aaaps.csv', 
     'bbbps.csv', 'ccc_info.csv', 'README.txt'] 
dataset_universe = {match for path in paths 
          for match in dataset_re.findall(path)} 

dataset_universe # {'aaa', 'bbb', 'ccc'} 


Regex объяснения скопированной из https://regex101.com/r/sR5cQ8:

^ assert position at start of the string 
1st Capturing group (.*) 
    .* matches any character (except newline) 
     Quantifier: * Between zero and unlimited times, as many times as possible, giving back as needed [greedy] 
(?:_values|_info|ps) Non-capturing group 
    1st Alternative: _values 
     _values matches the characters _values literally (case sensitive) 
    2nd Alternative: _info 
     _info matches the characters _info literally (case sensitive) 
    3rd Alternative: ps 
     ps matches the characters ps literally (case sensitive) 
\. matches the character . literally 
csv matches the characters csv literally (case sensitive) 
$ assert position at end of the string 

0

Вот еще один способ сделать это с помощью pandas:

Рассмотрим ваши входная папка c ontains файлы, как это:

aaa_info.csv 
aaa_values.csv 
aaapd.csv 
bbb_info.csv 
bbb_values.csv 
bbbpd.csv 
ccc_info.csv 
ccc_values.csv 
cccpd.csv 
ddd_info.csv 
ddd_values.csv 
dddpd.csv 

КОД

import os 
import glob 
import pandas as pd 

#Get all the csv files in the folder 
flist = [os.path.basename(x) for x in glob.glob(os.getcwd() + '\\*.csv')] 

#Create a dataframe 
df = pd.DataFrame() 

#Create a column named files and assign the file list to it 
df['files'] = flist 

#Create another column named set and assign only the portion of the file name that we want to create set by 
df['set'] = [x.rsplit('_')[0] if '_' in x else x[:-6] for x in flist] 

#Group by the set names required 
#if you want the output as sets 
dfs = df.groupby(df['set']).apply(lambda x: set(x['files'])) 

#if you want them to be CSV 
dfg = df.groupby(df['set']).apply(lambda x: ','.join(x['files'])) 

dfg.to_csv('setoffiles.csv') 

После будет выход произведенный

enter image description here

Смежные вопросы