Pandas 공부 정리
LeetCode, Project 등 진행하면서 모르는 것들, 헷갈리는 것들, 유용한 팁 정리
1. unique()
Second Highest Salary - LeetCode
salary = list(employee['salary'].unique())
salary.sort(reverse=True)
- 버전에 따라서 바로 sort가 되지 않는 경우도 있는데, sort_values를 사용해주면 된다.
- 인자에는 ascending=True
2. rank()
employee['dense_rank'] = employee['salary'].rank(method='dense',ascending=False).astype(int)
- SQL의 rank, dense rank처럼 등수를 매길 수 있다.
- method를 통해서 등수 매기는 유형 처리 가능.
- ascending을 통해서 오름차순, 내림차순 처리 가능.
- 새로운 컬럼을 지정하면서 바로 astype으로 데이터 유형을 체크 가능하다.
3. empty
Nth_salary = employee[employee['dense_rank'] == N]['salary']
if Nth_salary.empty:
Nth_salary = None
- 데이터 프레임, 시리즈가 비어있는지 확인하기 위한 메서드
- 파이썬 기본 자료형인 list, tuple처럼 not Nth_salary가 먹히지 않는다.
- 비어있는지 확인이 필요하면 길이를 체크해줘도 되지만 가독성 좋게 empty를 써보자.
4. sort_values()
scores.sort_values(by='rank', inplace=True)
- 정렬은 자주 나오는 편이다.
- 기준 없는 테이블에서는 새롭게 변수에 할당하지 않고 inplace를 통해서 데이터프레임 변경이 가능하다.
- df.sort_values[by=[columns1,columns2], ascending=[True,False])같이 다중 컬럼에서 설정이 가능하다.
5. merge()
Department Highest Salary - LeetCode
answer = pd.merge(high_salary_employee, department,
left_on='departmentId', right_on='id',
suffixes=('_high_salary_employee', '_department'))
- SQL의 join이랑 같은 역할이다.
- pandas에도 join은 있지만 인덱스 기반이라서 merge를 더 많이 사용한다고 한다.
- 컬럼명이 같은 경우 on을 통해서 join이 가능하다.
- 컬럼명이 다른 경우 left on, right on을 통해서 어떤 컬럼을 기준으로 join하는지 명시해야한다.
- suffixes같은 경우에는 join 이후에 컬럼명이 변하는데 어떤 테이블에서 왔는지 명시해주는 용도.
6. drop_duplicates()
Delete Duplicate Emails - LeetCode
import pandas as pd
def delete_duplicate_emails(person: pd.DataFrame) -> None:
person.sort_values(by='id', inplace=True)
person.drop_duplicates(subset='email', inplace=True)
- drop duplicates의 파라미터에 keep='first'라는 메서드를 쓰면 속도가 현저히 향상되는 것을 확인했다.
- 그냥 순회를 한 후 제거하는 방식보다는 명시적으로 지정해주면 효율적으로 처리하는 로직이 있는 듯
7. size(), count()
df.groupby('컬럼1').size()
df.groupby('컬럼1').count()
- SQL의 count(*)와 count(컬럼)의 차이. Null을 count하냐 안하냐의 차이다.
- 조건에 따라서 Null값을 카운팅 하는지, 안하는지 체크 후 사용하기.
8. filter()
import pandas as pd
def duplicate_emails(person: pd.DataFrame) -> pd.DataFrame:
duplicated_emails = person.groupby('email').filter(lambda x: len(x) > 1)
return pd.DataFrame({'Email':duplicated_emails['email'].unique()})
- 컬럼에 조건 넣어줄 때 filter를 사용한다. groupby에 지정된 단일컬럼 email이 iterable한 객체로 들어온다.
- 다중 컬럼을 지정한 경우 컬럼 명을 지정해야한다.
- 불리언인덱싱보다 느리게 동작하는듯.
9. isin()
Customers Who Never Order - LeetCode
def find_customers(customers: pd.DataFrame, orders: pd.DataFrame) -> pd.DataFrame:
answer = customers[~customers['id'].isin(orders['customerId'])][['name']]
answer.rename(columns={'name': 'Customers'}, inplace=True)
return answer
- isin()의 파라미터로 들어갔으면 T, 아닌 경우 F로 반환을 한다.
- 결과 값에 ~을 통해서 not in 역할을 할 수 있다.
10. shift()
def rising_temperature(weather: pd.DataFrame) -> pd.DataFrame:
weather.sort_values(by='recordDate',inplace=True)
weather['pre_temperature'] = weather['temperature'].shift(1)
weather['pre_recordDate'] = weather['recordDate'].shift(1)
result = weather[(weather['temperature'] > weather['pre_temperature']) &
((weather['recordDate'] - weather['pre_recordDate']) == timedelta(days=1))]
return result[['id']]
- shift를 통해서 이전 행의 값을 가져온다.
- shift에 음수 인덱스를 가져오면 이후 행의 값을 가져올 수 있다.
- 포인터를 그대로 두고 테이블을 한 칸 밑으로 이동시켜서 이전 값을 가져온다는 말.
- 그냥 양수면 이전 값, 음수면 이후 값이라고 생각하자.
11. diff()
def rising_temperature(weather: pd.DataFrame) -> pd.DataFrame:
weather.sort_values(by="recordDate", inplace=True)
return weather[
(weather.temperature.diff() > 0) & (weather.recordDate.diff().dt.days == 1)
][["id"]]
- diff를 통해서 이전 값들과 연산을 바로 실행할 수 있다.
- diff 인자는 기본적으로 1이 들어간다고 생각하면 된다.
- shift와 비슷하게 양수면 이전 갑스, 음수면 이후 값이라고 생각하자.
12. pivot_table(), groupby().집계().unstack()
import pandas as pd
from datetime import datetime, timedelta
def trips_and_users(trips: pd.DataFrame, users: pd.DataFrame) -> pd.DataFrame:
window = trips[trips['request_at'].between('2013-10-01','2013-10-03')]
unbanned = users[users['banned']=='No']
join = pd.merge(window, unbanned, left_on='client_id', right_on='users_id')
join = pd.merge(join, unbanned, left_on='driver_id', right_on='users_id')
grouped = join.groupby(['request_at', 'status']).size().unstack(fill_value=0)
- group화된 데이터프레임을 다룰 때, 세로로 stack된 형태를 우리가 평소에 생각하는 DataFrame 형태로 바꿔준다.
- fill_value를 안넣으면 기존에 비어있는 부분은 Null로 채워진다.
- pivot table과 비교하면, group화된 테이블에 전체 속성이 들어있지 않은 경우가 있는데, unstack을 사용해서 만드는 경우에는 아예 컬럼이 사라져버리는 문제가 발생한다.
- 단순 두 컬럼 사이에서 pivot table을 만드는 경우 pivot table을 사용해야 추가적인 연산이 적어진다.
13. transform('집계')
Game Play Analysis IV - LeetCode
import pandas as pd
def gameplay_analysis(activity: pd.DataFrame) -> pd.DataFrame:
activity.sort_values(by=['player_id', 'event_date'], inplace=True)
activity['first_date'] = activity.groupby('player_id')['event_date'].transform('min')
second = activity[activity['event_date'] == activity['first_date'] + timedelta(days=1)]
return pd.DataFrame({'fraction':[round(len(second['player_id'].unique())/len(activity['player_id'].unique()),2)]})
- groupby 이후에 집계함수를 쓰는 과정에서 min() vs transform('min')의 차이가 있다.
- 전자는 시리즈 형태로 반환돼서 기존 데이터 프레임에 병합하게 되면 컬럼 수가 맞지 않을 수 있다.
- 새 컬럼을 만들어서 기존 정보에 추가 정보를 만들어주고 싶으면 transform을 사용하자.
13. np.where
import pandas as pd
def triangle_judgement(triangle: pd.DataFrame) -> pd.DataFrame:
triangle['triangle'] = np.where((triangle['x'] + triangle['y'] <= triangle['z']) |
(triangle['y'] + triangle['z'] <= triangle['x']) |
(triangle['z'] + triangle['x'] <= triangle['y']),
'No', 'Yes')
return triangle
def triangle_judgement(triangle: pd.DataFrame) -> pd.DataFrame:
triangle['triangle'] = np.where((triangle['x'] + triangle['y'] > triangle['z']) &
(triangle['y'] + triangle['z'] > triangle['x']) &
(triangle['z'] + triangle['x'] > triangle['y']),
'Yes', 'No')
return triangle
- SQL의 IF와 같은 역할을 한다.
- 주어진 조건이 참이면 앞의 값, 아니면 뒤의 값으로 반환한다.
- 조건식에 다중조건을 넣어주면 연산하는데 오래 걸릴 수 있다.
- AND가 여러개면 반대 조건으로 걸어주고 OR로 바꿔주면 시간 단축이 가능하다.
14. apply()
import pandas as pd
def triangle_judgement(triangle: pd.DataFrame) -> pd.DataFrame:
def check(row):
x,y,z = row['x'],row['y'],row['z']
if x+y>z and y+z>x and z+x>y:
return 'Yes'
return 'No'
triangle['triangle'] = triangle.apply(check, axis=1)
return triangle
- 각 row를 입력으로 받아서 함수처리를 하고 값을 반환한다.
- row 단위로 입력이 들어와서 iterrows()랑 시간은 크게 차이가 나지 않는 듯 하다.
- 조건이 간단할 경우, lambda로 정의하고 간단하게 적용하는 것도 나쁘지 않아보인다.
'Data Analysis > SQL Pandas' 카테고리의 다른 글
leetcode : 1633. Percentage of Users Attended a Contest (0) | 2025.02.04 |
---|---|
leetcode : 1587. Bank Account Summary II (0) | 2025.02.04 |
leetcode : 1581. Customer Who Visited but Did Not Make Any Transactions (0) | 2025.02.03 |
[Pandas/MySQL] Active User (0) | 2024.11.14 |
[Pandas/MySQL] Rank (0) | 2024.11.12 |
[MySQL] Example (0) | 2024.08.29 |
[Pandas] Query Reference (0) | 2024.08.29 |
댓글