Объединение заголовков csv с соответствующими путями к файлу в новый файл - PullRequest
0 голосов
/ 03 июля 2018

Я не уверен, как "взломать" следующий Python-Nut. Поэтому я надеялся, что некоторые из вас, более опытных Python'еров, смогут подтолкнуть меня в правильном направлении.

Что я получил: Несколько каталогов, содержащих много CSV-файлов

Например:

/home/Date/Data1 /home/Date/Data2 /home/Date/Data3/sub1 /home/Date/Data3/sub2

Что я хочу: Файл, содержащий разделенный путь для каждого файла, за которым следуют переменные (= строка / заголовки) соответствующего файла. Как это:

home /t Date /t Data1 /t "variable1" "variable2" "variable3" ...
home /t Date /t Data2 /t "variable1" "variable2" "variable3" ...
home /t Date /t Data3 /t sub1 /t  "variable1" "variable2" "variable3" ...
home /t Date /t Data3 /t sub2 /t  "variable1" "variable2" "variable3" ...

Где я сейчас нахожусь?: Первым шагом было выяснить, как распечатать первую строку (переменные) одного CSV-файла (для тестирования я использовал файл test.txt)

# print out variables of a single file:
import csv
with open("test.txt") as f:
    reader = csv.reader(f)
    i = next(reader)

    print(i)

Вторым шагом было выяснить, как напечатать пути к файлам csv в каталогах, включая подпапки. Вот чем я закончил:

import os

# Getting the current work directory (cwd)
thisdir = os.getcwd()

# r=root, d=directories, f = files
for r, d, f in os.walk(thisdir):
    for file in f:
        if ".csv" in file:
            print(os.path.join(r, file))

Печать:

/home/Date/Data1/file1.csv
/home/Date/Data1/file2.csv
/home/Date/Data2/file1.csv
/home/Date/Data2/file2.csv
/home/Date/Data2/file3.csv
/home/Date/Data3/sub1/file1.csv
/home/Date/Data3/sub2/file1.csv
/home/Date/Data3/sub2/file2.csv

Где я застрял?: Я изо всех сил пытаюсь понять, как добраться отсюда, любые идеи, подходы и т. Д. В правильном направлении, очень ценится!

Приветствия, B

##### ОБНОВЛЕНИЕ #####

Вдохновленный полезными комментариями Тима Пицкера, я прошел долгий путь (Спасибо, Тим!). Но я не смог заставить работать output.write & join, поэтому код немного другой. Новая проблема теперь состоит в том, чтобы «объединить» два списка в виде двух отдельных столбцов с запятой в качестве разделителя (я хочу создать файл CSV). Так как я застрял, еще раз, я хотел посмотреть, есть ли какие-нибудь хорошие предложения от опытных питонеров?

#!/usr/bin/python
import os
import csv
thisdir = os.getcwd()

# Extract file-paths and append them to "csvfiles"
for r, d, f in os.walk(thisdir):        # r=root, d=directories, f = files
    for file in f:
        if ".csv" in file:
            csvfiles.append(os.path.join(r, file))

# get each file-path on new line + convert to list of str
filepath = "\n".join(["".join(sub) for sub in csvfiles])
filepath = filepath.replace(".csv", "")  # remove .csv
filepath = filepath.replace("/", ",")    # replace / with ,

Результат:

,home,Date,Data1,file1
,home,Date,Data1,file2
,home,Date,Data1,file3
... and so on

Затем к заголовкам:

# Create header-extraction function:
def get_csv_headers(filename):
    with open(filename, newline='') as f:
        reader = csv.reader(f)
        return next(reader)

# Create empty list for headers
headers=[]

# Extract headers with the function and append them to "headers" list
for l in csvfiles:
    headers.append(get_csv_headers(l))

# Create file with headers
headers = "\n".join(["".join(sublst) for sublst in headers]) # new lines + str conversion
headers = headers.replace(";", ",") # replace ; with ,

Результаты:

variable1,variable2,variable3
variable1,variable2,variable3,variable4,variable5,variable6
variable1,variable2,variable3,variable4
and so on..

Что я хочу сейчас: CSV, как это:

home,Date,Data1,file1,variable1,variable2,variable3
home,Date,Data1,file2,variable1,variable2,variable3,variable4,variable5,variable6
home,Date,Data1,file3, variable1,variable2,variable3,variable4

Например:

with open('text.csv', 'w') as f:
    writer = csv.writer(f, delimiter=',')
    writer.writerows(zip(filepath,headers))

В результате:

",",v
h,a
o,r
m,i,
e,a
and so on..

Любые идеи и толчки в правильном направлении приветствуются!

Ответы [ 2 ]

0 голосов
/ 05 июля 2018

О вашем редактировании: я бы рекомендовал не преобразовывать все в строки, которые находятся в начале процесса. Гораздо больше смысла хранить данные в структурированном формате и позволить модулям, разработанным для обработки структурированных данных, делать все остальное. Таким образом, ваша программа может выглядеть примерно так:

#!/usr/bin/python
import os
import csv
thisdir = os.getcwd()

# Extract file-paths and append them to "csvfiles"
for r, d, f in os.walk(thisdir):        # r=root, d=directories, f = files
    for file in f:
        if ".csv" in file:
            csvfiles.append(os.path.join(r, file))

Это (взято непосредственно из вашего вопроса) оставляет вам список имен файлов CSV.

Теперь давайте прочитаем эти файлы. Из сценария в вашем вопросе кажется, что ваши CSV-файлы на самом деле разделены точкой с запятой, а не запятыми. Это распространено в Европе (потому что запятая нужна в качестве десятичной точки), но Python нужно сказать, что:

# Create header-extraction function:
def get_csv_headers(filename):
    with open(filename, newline='') as f:
        reader = csv.reader(f, delimiter=";")  # semicolon-separated files!
        return next(reader)

# Create empty list for headers
headers=[]

# Extract headers with the function and append them to "headers" list
for l in csvfiles:
    headers.append(get_csv_headers(l))

Теперь headers - это список, содержащий множество подсписков (которые содержат все заголовки как отдельные элементы, так же, как они нам нужны).

Давайте не будем пытаться поместить все в одну строку; лучше держать его читабельным:

with open('text.csv', 'w', newline="") as f:
    writer = csv.writer(f, delimiter=',') # maybe use semicolon again??
    for path, header in zip(csvfiles, headers):
        writer.writerow(list(path.split("\\")) + header)

Если все ваши пути начинаются с \, вы также можете использовать

        writer.writerow(list(path.split("\\")[1:]) + header)

, чтобы избежать пустого поля в начале каждой строки.

0 голосов
/ 03 июля 2018

Это выглядит многообещающе; Вы уже сделали большую часть работы.

Что бы я сделал, это

  1. Соберите все ваши имена файлов CSV в списке. Поэтому вместо печати имен файлов создайте пустой список (csvfiles=[]) перед циклом os.walk() и сделайте что-то вроде csvfiles.append(os.path.join(r, file)).
  2. Затем выполните итерацию по этим именам файлов, передавая каждое из подпрограмм, которые в настоящее время используются для чтения test.txt. Если вы поместите это в функцию, она может выглядеть так:

def get_csv_headers(filename):
    with open(filename, newline="") as f:
        reader = csv.reader(f)
        return next(reader)
  1. Теперь вы можете записать разделенное имя файла в новый файл и добавить заголовки. Я немного подвергаю сомнению формат вашего файла - почему разделять часть строки символами табуляции, а остальные - пробелами (и кавычками)? Если вы настаиваете на этом, вы можете использовать что-то вроде

output.write("\t".join(filename.split("\\"))
output.write("\t")
output.write(" ".join(['"{}"'.format(header) for header in get_csv_headers(filename)])

но вы можете переосмыслить этот подход. Стандартный формат, такой как JSON, может быть более читабельным и переносимым.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...