Как манипулировать CSV в python с одинаковыми значениями в столбце и создать новый с уникальными значениями - PullRequest
0 голосов
/ 31 октября 2018

Проблема, с которой мне приходится сталкиваться, заключается в том, что у меня есть файл CSV с одними и теми же данными в нескольких столбцах (здесь - уникальный_код), и я хочу создать новый CSV, содержащий только один раз данные для этого столбца и данные из других столбцов должны быть разделены пробелом, если они отличаются (здесь код альтернативы).

Вот мой CSV.

Уникальное_кодовое описание альтернативный_код

33;product1;58

43;product2;95

33;product1;62

68;product3;11

43;product2;99

Мой желаемый результат CSV:

33;product1;58 62

43;product2;95 99

68;product3;11

Любые идеи о том, как я могу реализовать мой новый CSV?

Ответы [ 4 ]

0 голосов
/ 31 октября 2018

littletable - это тонкая CSV-оболочка, которую я написал несколько лет назад. Таблицы в littletable представляют собой списки объектов с некоторыми вспомогательными методами для фильтрации, объединения, поворота, а также простым импортом / экспортом данных CSV, JSON и данных фиксированного формата. Как и pandas, он помогает с импортом / экспортом данных, но не имеет всех других числовых аналитических функций, которые есть у pandas. Он также хранит все данные в памяти в виде списка объектов Python, поэтому он не будет обрабатывать миллионы строк, как это делает панда. Но если ваши потребности скромны, то, возможно, вам понадобится более короткая кривая обучения для работы с littletable.

Загрузка ваших исходных необработанных данных в небольшую таблицу начинается с:

import littletable as lt
data = open('raw_data.csv')
tt = lt.Table().csv_import(data, fieldnames="id name altid".split(), delimiter=';')

(Если во входном файле есть строка заголовка, csv_import будет использовать это и не потребует, чтобы вы указали fieldnames.)

Распечатка строк выглядит как перебор списка:

for row in tt:
    print(row)

печать:

{'name': 'product1', 'altid': '58', 'id': '33'}
{'name': 'product2', 'altid': '95', 'id': '43'}
{'name': 'product1', 'altid': '62', 'id': '33'}
{'name': 'product3', 'altid': '11', 'id': '68'}
{'name': 'product2', 'altid': '99', 'id': '43'}

Поскольку мы будем группировать и объединять атрибуты id, мы добавим индекс:

tt.create_index("id")

(Также могут быть созданы уникальные индексы, но в этом случае в исходном вводе есть повторяющиеся значения с тем же идентификатором.)

Таблицы могут быть сгруппированы по одному или нескольким атрибутам, а затем каждая группа записей может быть передана в функцию, чтобы получить совокупное значение для этой группы. В вашем случае вам нужны все собранные altids для каждого продукта id.

def aggregate_altids(rows):
    return ' '.join(set(row.altid for row in rows if row.altid != row.id))
grouped_altids = tt.groupby("id", altids=aggregate_altids)

for row in grouped_altids:
    print(row)

Дает:

{'altids': '62 58', 'id': '33'}
{'altids': '99 95', 'id': '43'}
{'altids': '11', 'id': '68'}

Теперь мы объединяем эту таблицу с исходной таблицей tt на id и раскладываем дубликаты:

tt2 = (grouped_altids.join_on('id') + tt)().unique("id")

и распечатать результаты:

for row in tt2:
    print("{id};{name};{alt_ids}".format_map(vars(row)))

Предоставление:

33;product1;58 62
43;product2;95 99
68;product3;11

Общий код без отладки выглядит так:

# import
import littletable as lt
with open('raw_data.csv') as data:
    tt = lt.Table().csv_import(data, fieldnames="id name altid".split(), delimiter=';')
tt.create_index("id")

# group
def aggregate_altids(rows):
    return ' '.join(set(row.altid for row in rows if row.altid != row.id))
grouped_altids = tt.groupby("id", alt_ids=aggregate_altids)

# join, dedupe, and sort
tt2 = (grouped_altids.join_on('id') + tt)().unique("id").sort("id")

# output
for row in tt2:
    print("{id};{name};{alt_ids}".format_map(vars(row)))
0 голосов
/ 31 октября 2018
import csv

with open("my_file.csv", 'r') as fd:
    #import csv as list of list and remove blank line                
    data = [i for i in csv.reader(fd, delimiter=';') if i]                                       
    result = []
    for value in data:
        #check if product not in result 
        if value[1] not in [r[1] for r in result if r]:
            #add the new product to result with all values for the same product 
            result.append([value[0],
                           value[1],
                           ' '.join([line[2] for line in data if line[1] == value[1]])
                         ])
    print(result)
0 голосов
/ 31 октября 2018

Наконец я в конечном итоге к этому решению:

# -*- coding: utf-8 -*-
import csv

input_file_1 = "eidi.csv"
output_file = "output.csv"

parsed_dictionary={}

def concatenate_alter_codes(alter_code_list):
    result = ""
    for alter_code in alter_code_list:
        result = result + (alter_code + " ")
        print result
    return result[:-1]

#Read input csv file and create a dictionary with a list of all alter codes
with open(input_file_1,'r') as f:
    # put ; symbol as delimeter
    input_csv=csv.reader(f,delimiter=';')
    for row in input_csv:
        # if the key exists in the dictionary
    if row[0] in parsed_dictionary:
        parsed_dictionary[row[0]][0].append(row[2])
    else:
        parsed_dictionary[row[0]] = [[row[2]], row[1], row[3], row[4], row[5], row[6]]

#create new csv file with concatenated alter codes

with open(output_file,'w') as f:
    for key in parsed_dictionary:
                f.write(key + ";" + concatenate_alter_codes(parsed_dictionary[key][0]) + ";" + parsed_dictionary[key][1] + ";" + parsed_dictionary[key][2] + ";" + parsed_dictionary[key][3] + ";" + parsed_dictionary[key][4] + ";" + parsed_dictionary[key][5] + "\n")
0 голосов
/ 31 октября 2018

Вы можете попробовать что-то вроде:

vals = {}
names = {}
with open(input_filename,'r') as file:
    for line in file:
        l = line.replace("\n","")
        l = l.split(";")
        if(vals.has_key(l[0])):
            vals[l[0]].append(l[2])
        else:
            vals[l[0]] = [l[2]]
            names[l[0]] = l[1]

with open(output_filename,'w') as file:
    for key in vals.keys():

        res = str(key)+";"+str(names[key])+";"+str(vals[key][0])

        for i in range(0,len(vals[key])-1):
            res += " "+vals[key][i+1]
        res += '\n'

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