CSV를 읽고 중복 요소를 포함하는 목록을 제거하고 싶습니다.

14447 단어 CSV파이썬pandas
일로 툴의 작성시 고전해 버렸으므로 비망록 정도에 메모해 둡니다.

경위



데이터의 해석을 위해서, 폴더에 들어 있는 CSV를 모두 읽어들여 그 안의 수열 취득해, 결합해 2차원 배열을 만든 후, 리스트안의 리스트에 있는 최종열이 중복하고 있는 리스트를 제거하고 CSV로 내보내는 도구를 만들고 싶었습니다.

하고 싶은 일



예: CSV를 로드하여 이런 느낌의 2차원 배열을 만듭니다.



[["A", "B", "C", "D", "1"], ["D", "F", "G", "A", "2"], ["O", "P", "Q", "C", "1"], ["L", "M", "T", "H", "2"], ["A", "B", "Z", "D", "3"]]


1열
2열
3열
4열
5열


A
B
C
D
1

D
F
G
A
2

O
P
Q
C
1

L
M
T
H
2

A
B
Z
D
3


이 다섯 번째 열의 중복 목록을 다음과 같이 제거합니다 (하나 남아 있으면 순서가 변경 될 수 있음)

[["A", "B", "C", "D", "1"], ["D", "F", "G", "A", "2"], ["A", "B", "Z", "D", "3"]]


1열
2열
3열
4열
5열


A
B
C
D
1

D
F
G
A
2

A
B
Z
D
3


즉, 단순하게 list(set(lst)) 를 사용할 수 없다···.
그래서 처음에는 다음과 같은 느낌의 코드를 써 보았다.
import csv
from glob import glob

col5 = []

def main():
    path = "/hogeDir"
    pathList = glob(f"{path}/*.csv")
    lst = []
    for pl in pathList:
        lst += inputCsv(pl)

    print(deduplicationList(lst))

def inputCsv(path: str) -> list:
    lst = []
    lst2 = []

    with open(path) as f:
        reader = csv.reader(f)
        next(reader)
        for line in reader:
            lst += line
            lst2 += [line[4]]
            col5 += line[4]
    return joinList(lst, lst2)

def joinList(lst1: list, lst2: list) -> list:
    tmpList = []
    for i, l in zip(lst1, lst2):
        tmpList = [i + l]
    return tmpList

def deduplicationList(lst: list) -> list:
    tmplist = lst
    for i, v in enumerate(tmplist):
        if v == col5[i]:
            lst.pop(i)
            col5.pop(i)
    return lst

if __name__ == "__main__":
    main()

일단 CSV 전부를 취득해 연결한 후, main()lstcol5왠지 인덱스 에러나 원래 lstcol5 의 길이가 일치하지 않는다.
같은 CSV를 읽고 함께 pop() 하고 있을 것인데 어쩐지 잘 되지 않는다・・・.

pandas를 사용하여 중복 목록 제거



버그가 고치지 않고, 시간이 걸려 버렸기 때문에, 이미 포기하고 다른 방법을 생각하려고 Web를 모색해, 이하의 기사를 발견했다.
csv 데이터가 중복됩니다 ~ -> 그것, pandas로 제외

과연, pandas를 사용하면 제거할 수 있을까!
하지만 2차원 배열은 어떻습니까…
더 모색했다.
pandas.DataFrame, Series의 중복 행을 추출 및 삭제

list를 pandas로 읽어들여 duplicated즉시 써 보았다.
import pandas as pd

def main():
    path = "/hogeDir"
    pathList = glob(f"{path}/*.csv")
    pdlist = pd.DataFrame([], columns=["1列", "2列", "3列", "4列", "5列"])
    for pl in pathList:
        pd.concat(pdlist, pd.DataFrame(inputCsv(pl), columns=["1列", "2列", "3列", "4列", "5列"]))

    pdlist = pdlist.drop_duplicates(subset="5列", keep="first")
    pdlist.to_csv(f"{path}/output.csv", index=False)

굉장히 간단했다…게다가 약 2000행 읽고 있을 것인데 빠르다!
온순하게 pandas를 사용하면 좋았다.

요약



결과적으로 하고 싶은 것이 한 줄로 되어 버렸다. 게다가 빠르다.
pandas 다양한

참고 사이트



csv 데이터가 중복됩니다 ~ -> 그것, pandas로 제외
pandas.DataFrame, Series의 중복 행을 추출 및 삭제
[python] 사전에서 동일한 키에 여러 값을 등록합니다.

【추기】Dictionary를 사용해 중복되지 않는 리스트의 작성



사전형에는 하나의 키에는 하나의 값만 등록되어 덮어씁니다.
즉, CSV를 읽을 때 중복하고 싶지 않은 값을 Key로 등록하면 중복되지 않는 목록을 만들 수 있습니다.
from collections import defaultdict

def main():
    path = "/hogeDir"
    dic = defaultdict(list)
    pathList = glob(f"{path}/*.csv")

    for pl in pathList:
        dic.update(inputCsv(pl))

    print(dic.values())

def inputCsv(path: str):
    inputDic = defaultdict(list)
    with open(path) as f:
        reader = csv.reader(f)
        next(reader)
        for line in reader:
            inputDic[line[4]] = line
    return inputDic

이번 경우, 총 2000행 이상의 CSV를 읽고 있었으므로, 그 경우 pandas를 사용하는 것이 빠릅니다만,
그렇게 많지 않은 경우는 이 방법을 사용해도 좋을지도 모릅니다.

좋은 웹페이지 즐겨찾기