[오늘의 문제] Customers Who Never Order

shlim55·2025년 11월 23일

코딩테스트

목록 보기
183/223

출처: https://leetcode.com/problems/customers-who-never-order/description/?envType=study-plan-v2&envId=30-days-of-pandas&lang=pythondata

테이블:Customers

+-------------+---------+
| 열 이름 | 유형 |
+-------------+---------+
| 아이디 | 정수 |
| 이름 | varchar |
+-------------+---------+
id는 이 테이블의 기본 키(고유한 값을 갖는 열)입니다.
이 표의 각 행은 고객의 ID와 이름을 나타냅니다.

테이블:Orders

+-------------+------+
| 열 이름 | 유형 |
+-------------+------+
| 아이디 | 정수 |
| 고객 ID | 정수 |
+-------------+------+
id는 이 테이블의 기본 키(고유한 값을 갖는 열)입니다.
customerId는 Customers 테이블의 ID에 대한 외래 키(참조 열)입니다.
이 표의 각 행은 주문 ID와 주문한 고객의 ID를 나타냅니다.

아무것도 주문하지 않은 모든 고객을 찾는 솔루션을 작성하세요.

결과 표를 원하는 순서 대로 반환합니다 .

결과 형식은 다음 예와 같습니다.

예 1:

입력:
고객 테이블:
+----+-------+
| 아이디 | 이름 |
+----+-------+
| 1 | 조 |
| 2 | 헨리 |
| 3 | 샘 |
| 4 | 최대 |
+----+-------+
주문표:
+----+------------+
| 아이디 | 고객 아이디 |
+----+------------+
| 1 | 3 |
| 2 | 1 |
+----+------------+
산출:
+----------+
| 고객 |
+----------+
| 헨리 |
| 맥스 |
+----------+

내가 한 풀이

import pandas as pd
import numpy as np
def find_customers(customers: pd.DataFrame, orders: pd.DataFrame) -> pd.DataFrame: # 아무것도 주문하지 않은 모든 고객을 찾는 솔루션을 작성하세요.
    # 두 df merge
    left_df = pd.merge(customers, orders,
                        left_on='id',      # customers DataFrame의 키
                        right_on='customerId', # orders DataFrame의 키
                        how='left'         # 왼쪽(customers) DataFrame의 모든 데이터를 유지
                        )

    # print('레프트조인 결과', left_df)
    
    no_order_customers = left_df[left_df['customerId'].isna()]
    no_order_customers = no_order_customers.rename(columns={'name':'customers'})
    return no_order_customers[['customers']] # cusomerId랑 일치하지 않는 이름들 반환  


customer_data = {
    'id' : [1, 2, 3, 4],
    'name' : ['Joe', 'Henry', 'Sam', 'Max']
}
customers = pd.DataFrame(customer_data)


order_data = {
    'id' : [1, 2],
    'customerId' : [3, 1]
}

orders = pd.DataFrame(order_data)

result = find_customers(customers, orders) # 출력결과는 이름 

print(result)

트러블 슈팅
처음에 customer_data, order_data 각각 두개의 테이블 처럼 분리하듯
데이터 프레임 분리하는것도 익숙 하지 않았다.
거기다가 left_on, right_on은 처음 배운 개념..

그외에 레프트 조인, isna 활용(일치 하지 않는 행 조회), column명 변경
다른 공부 하다보니 까먹었다..😅

게다가 SQL 개념을 판다스에다 적용하려니 힘들다..

개념SQL (데이터베이스)Pandas (파이썬)
데이터 구조테이블 (Table)데이터프레임 (DataFrame)
연결(Join)JOINpd.merge()
연결 기준ON Table1.Key = Table2.ForeignKeyleft_on= , right_on=
필터링 (NULL)WHERE Column IS NULLdf[df['Column'].isna()]

머지를 안쓴 풀이 제미나이의 풀이

import pandas as pd

def find_customers_alt(customers: pd.DataFrame, orders: pd.DataFrame) -> pd.DataFrame:
    # 1. 주문 테이블에서 'customerId' 열의 고유한 값(즉, 주문한 고객 ID)을 가져옵니다.
    #    결과는 pandas Series 또는 NumPy 배열이 됩니다.
    ordered_ids = orders['customerId'].unique()
    
    # 2. 고객(customers) DataFrame을 필터링합니다.
    #    customers['id'].isin(ordered_ids): 'id'가 ordered_ids에 포함되면 True
    #    ~: (틸드)는 NOT 연산자로, 결과가 True인 것을 False로, False인 것을 True로 반전시킵니다.
    #    즉, 주문 ID 리스트에 포함되지 않는 고객만 선택합니다.
    no_order_customers = customers[~customers['id'].isin(ordered_ids)]
    
    # 3. 요구 사항에 맞게 'name' 열만 선택하고 컬럼 이름을 'customers'로 변경합니다.
    result_df = no_order_customers[['name']] 
    result_df = result_df.rename(columns={'name': 'customers'})
    
    return result_df

# --- 데이터 ---
customer_data = {
    'id' : [1, 2, 3, 4],
    'name' : ['Joe', 'Henry', 'Sam', 'Max']
}
customers = pd.DataFrame(customer_data)

order_data = {
    'id' : [1, 2],
    'customerId' : [3, 1]
}
orders = pd.DataFrame(order_data)

# --- 함수 실행 및 출력 ---
result = find_customers_alt(customers, orders) 

print("--- 대체 풀이 최종 결과 ---")
print(result)
profile
A Normal Programmer

0개의 댓글