본문 바로가기
Python/기본문법

리스트 내 중복값 제거하기 (Python)

by yororing 2024. 11. 25.

00 개요

  • 리스트를 다루는 도중 리스트 안에 중복된 값이 존재할 때, 중복되지 않는 값들만 담은 리스트를 생성하는 방법에 대한 정리
  • 크게 두 분류로, 본래 리스트 안의 중복되지 않는 값들의 순서 보존 여부로 나뉨
순서 보존 안 됨 순서 보존됨
  • set() 사용 
  • pandas 라이브러리의 Series 객체의 value_counts 사용
  • itertools 라이브러리의 groupby 사용
  • dict.fromkeys() 사용 
  • loop 사용 
  • list comprehension 사용 
  • pandas 라이브러리의 unique() 사용
  • pandas 라이브러리의 Series 객체의 drop_duplicates 사용
  • 언제  어떤 사용법을 적용해야 할까?
    • 순서를 지켜야할 경우: dict.fromkeys(), loop, list comprehension 등 사용
    • 순서를 안 지켜도 되는 경우: set() 사용
    • 데이터셋이 클 경우: 성능을 위해 set() 또는 pandas.unique() 사용

01 사용 방법

1. set() 사용

  • 가장 간단한 방법 
  • 원래 list를 set으로 변환시킨 다음 다시 list로 변환하는 방법
  • 원래 순서가 보존되지 않음
original_list = [0, 2, 1, 4, 4, 2, 6, 3, 2, 3]
print('original:', original_list)
# original: [0, 2, 1, 4, 4, 2, 6, 3, 2, 3]

set_unique = set(original_list)
set_unique_list = list(set(original_list))

print('set_unique:', set_unique)
print('type:', (type(set_unique)))
print('set_unique_list:',set_unique_list)
# set_unique: {0, 1, 2, 3, 4, 6} (순서 보존 안 됨)
# type: <class 'set'>
# set_unique_list: [0, 1, 2, 3, 4, 6] (순서 보존 안 됨)

2. dict.fromkeys() 사용

  • Python3.7 버전부터 dictionary 객체는 주입 순서 (insertion order)를 보존함
  • dict.fromkeys() 메소드를 사용하여 중복된 값 제거하는 동시 원래 순서도 보존됨 
original_list = [0, 2, 1, 4, 4, 2, 6, 3, 2, 3]
print('original:', original_list)
# original: [0, 2, 1, 4, 4, 2, 6, 3, 2, 3]

dict_unique = dict.fromkeys(original_list)
dict_unique_list = list(dict.fromkeys(original_list))

print('dict_unique:', dict_unique)
print('type:', (type(dict_unique)))
print('dict_unique_list:',dict_unique_list)
# dict_unique: {0: None, 2: None, 1: None, 4: None, 6: None, 3: None}
# type: <class 'dict'>
# dict_unique_list: [0, 2, 1, 4, 6, 3]

3. Loop 사용

  • 수동적으로 원래 리스트를 반복하며 고유한 값들만 새 리스트에 추가하는 방법
  • 원래 순서 보존됨
original_list = [0, 2, 1, 4, 4, 2, 6, 3, 2, 3]
print('original:', original_list)
# original: [0, 2, 1, 4, 4, 2, 6, 3, 2, 3]

loop_list = list()
for i in range(len(original_list)):
    if original_list[i] not in loop_list:
        loop_list.append(original_list[i])
        
print('loop_list:', loop_list)
# loop_list: [0, 2, 1, 4, 6, 3]

4. List Comprehension 사용

  • for loop를 더 간결하게 사용하는 방법
  • 원래 순서 보존됨
original_list = [0, 2, 1, 4, 4, 2, 6, 3, 2, 3]
print('original:', original_list)
# original: [0, 2, 1, 4, 4, 2, 6, 3, 2, 3]

list_comp_list = []
[list_comp_list.append(val) for val in original_list if val not in list_comp_list]

print('list_comp_list:', list_comp_list)
# list_comp_list: [0, 2, 1, 4, 6, 3]

5. pandas의 unique() 사용

  • 고유한 값 반환하는 메소드
  • 원래 순서 보존됨 
original_list = [0, 2, 1, 4, 4, 2, 6, 3, 2, 3]
print('original:', original_list)
# original: [0, 2, 1, 4, 4, 2, 6, 3, 2, 3]

import pandas

pd_unique = pandas.unique(original_list)
pd_unique_list = pd_unique.tolist() # 또는 list(pd_unique)
print('pd_unique:', pd_unique)
print('type:', (type(pd_unique)))
print('pd_unique_list:',pd_unique_list)
# pd_unique: [0 2 1 4 6 3]
# type: <class 'numpy.ndarray'>
# pd_unique_list: [0, 2, 1, 4, 6, 3]

6. pandas의 Series 객체 사용

1) Series 객체의 drop_duplicates() 사용

  • pandas.Series에서 중복된 값을 제거하는 메서드
  • 원래 순서 보존됨 
original_list = [0, 2, 1, 4, 4, 2, 6, 3, 2, 3]
print('original:', original_list)
# original: [0, 2, 1, 4, 4, 2, 6, 3, 2, 3]

import pandas

series = pandas.Series(original_list)
series_unique = series.drop_duplicates()
series_unique_list = series_unique.tolist()

print('series:', series)
print('type:', (type(series)))
print('series_unique:', series_unique)
print('type:', (type(series_unique)))
print('series_unique_list:',series_unique_list)
# series: 0    0
# 1    2
# 2    1
# 3    4
# 4    4
# 5    2
# 6    6
# 7    3
# 8    2
# 9    3
# dtype: int64
# type: <class 'pandas.core.series.Series'>
# series_unique: 0    0
# 1    2
# 2    1
# 3    4
# 6    6
# 7    3
# dtype: int64
# type: <class 'pandas.core.series.Series'>
# series_unique_list: [0, 2, 1, 4, 6, 3]

2) Series 객체의 value_counts() 사용

  • pandas.Series에서 각 값의 개수를 추출하여, 그들의 고유값을 추출하는 방법
  • 원래 순서가 보존되지 않음
original_list = [0, 2, 1, 4, 4, 2, 6, 3, 2, 3]
print('original:', original_list)
# original: [0, 2, 1, 4, 4, 2, 6, 3, 2, 3]

import pandas

series = pandas.Series(original_list)
series_val_cnts = series.value_counts()  # 개수가 가장 많은 순으로 정렬됨
series_val_cnts_idx = series_val_cnts.index

print('series:', series)
print('type:', (type(series)))
print('series_val_cnts:', series_val_cnts)
print('type:', (type(series_val_cnts)))
print('series_val_cnts_idx:',series_val_cnts_idx)
print('type:', (type(series_val_cnts)))
# series: 0    0
# 1    2
# 2    1
# 3    4
# 4    4
# 5    2
# 6    6
# 7    3
# 8    2
# 9    3
# dtype: int64
# type: <class 'pandas.core.series.Series'>
# series_val_cnts: 2    3
# 4    2
# 3    2
# 0    1
# 1    1
# 6    1
# Name: count, dtype: int64
# type: <class 'pandas.core.series.Series'>
# series_val_cnts_idx: Index([2, 4, 3, 0, 1, 6], dtype='int64')
# type: <class 'pandas.core.series.Series'>
# series_val_cnts_idx_list: [2, 4, 3, 0, 1, 6]

7. itertools의 groupby 메소드 사용

  • 성능을 위해 itertools를 사용하여 hashable 객체를 포함한 리스트 안에 있는 중복값들 제거 가능
  • groupby 메소드는 연속된 중복값만 제거하기 때문에 사용하기 전에 원래 리스트를 정렬해줘야 됨
  • 그러므로 원래 순서 보존 안 됨 
original_list = [0, 2, 1, 4, 4, 2, 6, 3, 2, 3]
print('original:', original_list)
# original: [0, 2, 1, 4, 4, 2, 6, 3, 2, 3]

from itertools import groupby

# 원래 리스트 정렬 안 할 경우
gb_list = [key for key, _ in groupby(original_list)]
print('gb_list:', gb_list)
# gb_list: [0, 2, 1, 4, 2, 6, 3, 2, 3]  # 연속된 숫자 4만 중복값 제거됨, 나머지는 그대로 유지

# 원래 리스트 정렬 한 경우
gb_unique_list = [key for key, _ in groupby(sorted(original_list))]
print('gb_unique_list:', gb_unique_list)
# gb_unique_list: [0, 1, 2, 3, 4, 6] # 중복값 제거됨, 그러나 순서 보존 안 됨