프레임 속에 있는 수많은 데이터 중에, 내가 원하는 대상의 데이터만 골라 새로운 프레임으로 만들기
판다스에서는 loc 프로퍼티로 수행 가능
id | name | |
---|---|---|
0 | 0 | a |
1 | 1 | b |
2 | 2 | c |
3 | 3 | a |
4 | 4 | a |
5 | 5 | b |
6 | 6 | c |
df2 = df.loc[df['name'] == 'a']
df2.head()
id | name | |
---|---|---|
0 | 0 | a |
3 | 3 | a |
4 | 4 | a |
targets = ['a', 'c']
targets = ['a', 'c']
df3 = df.loc[df['name'].isin(targets)]
df3.head()
id | name | |
---|---|---|
0 | 0 | a |
2 | 2 | c |
3 | 3 | a |
4 | 4 | a |
6 | 6 | c |
# isin(targets) 와 동일한 결과
df3 = df.loc[(df['name'] == 'a') | (df['name'] == 'c')]
df3.head()
# isin(targets) 이고, id가 4보다 작은 데이터들
df4 = df.loc[(df['name'].isin(targets)) & (df['id'] < 4)]
df4.head()
id | name | |
---|---|---|
0 | 0 | a |
2 | 2 | c |
3 | 3 | a |
4 | 4 | a |
6 | 6 | c |
id | name | |
---|---|---|
0 | 0 | a |
2 | 2 | c |
3 | 3 | a |
df5 = df.loc[~df['name'].isin(targets)]
df5.head()
id | name | |
---|---|---|
1 | 1 | b |
5 | 5 | b |
id | name | location | |
---|---|---|---|
0 | 0 | a | 서울 |
1 | 1 | b | 부산 |
2 | 2 | c | 대구 |
3 | 3 | a | 서울 |
4 | 4 | a | 인천 |
5 | 5 | b | 여수 |
6 | 6 | c | 대전 |
series = df["location"]
series.head()
0 서울
1 부산
2 대구
3 서울
4 인천
Name: location, dtype: object
frame = df[["id", "location"]]
frame.head()
id | location | ||
---|---|---|---|
0 | 0 | 서울 | |
1 | 1 | 부산 | |
2 | 2 | 대구 | |
3 | 3 | 서울 | |
4 | 4 | 인천 |
frame = df.loc[df["name"]=="a", ["id", "location"]]
frame.head()
id | location | ||
---|---|---|---|
0 | 0 | 서울 | |
3 | 3 | 서울 | |
4 | 4 | 인천 |
df.groupby(분할 기준 컬럼)[적용 기준 칼럼].집계함수
by
: 분할 기준 컬럼(목록)as_index
: 분할 기준 컬럼들을 인덱스로 사용할 것인지 여부agg
함수를 사용해야 함df.groupby(['쇼핑몰 유형'])['수량'].mean()
쇼핑몰 유형에 따른 수량의 평균
df.groupby(['쇼핑몰 유형'], as_index=False)['수량'].mean()
쇼핑몰 유형에 따른 수량의 평균, 최대값
df.groupby(['쇼핑몰 유형'])[['수량','판매금액']].agg(['mean','max'])
쇼핑몰 유형과 제품에 따른 수량, 판매금액의 최대값-최소값: 사용자 함수 적용
def my_func(value):
return max(value) - min(value)
df.groupby(['쇼핑몰 유형', '제품'])[['수량','판매금액']].agg(my_func)
def my_func(value):
return max(value) - min(value)
df.groupby(['쇼핑몰 유형', '제품'], as_index=False)[['수량','판매금액']].agg(my_func)
※ Pandas에서 집계함수는 Series 객체를 인자로 받는다는 점이 포인트!
import pandas as pd
df_dict = {
'성별':['남자', '여자', '남자', '여자', '여자', '남자', '남자', '여자'],
'이름':['박영진', '김지혜', '김철수', '박유니', '김민혜', '김민철', '구태원', '김민주'],
'키':[170, 150, 188, 160, 160, 176, 181, 155]
}
df = pd.DataFrame(df_dict)
# 1. 성별로 '김'씨가 몇 명인지 집계
def get_lastname_count(series):
res = len([ _ for x in series if x[0]=='김'])
return res
# 언더바(_)는 명시적으로 뭔가를 받아야 하지만 그 값이 필요 없을 때 임시로 사용하는 것
df.groupby('성별').agg({'이름':get_lastname_count}).reset_index()
# 2. groupby를 이용하여 남자는 키가 180 이상인 사람, 여자는 키 160 이상인 사람의 수를 계산
def get_count_by_height(series):
if df.iloc[series.index[0], :]['성별'] == '남자':
res = len([_ for x in series if x>=180])
else:
res = len([_ for x in series if x>=160])
return res
df.groupby('성별').agg({'키':get_count_by_height}).reset_index()
import pandas as pd
df = pd.DataFrame({'date': ['29/10/24', '30/10/24', '31/10/24']})
print(df.dtypes_
df
date object
dtype: object
date | |
---|---|
0 | 29/10/24 |
1 | 30/10/24 |
2 | 31/10/24 |
infer_datetime)_format = True
df['date1'] = pd.to_datetime(df['date']. format = '%d/%m/%y')
df
date | date1 | |
---|---|---|
0 | 29/10/24 | 2024-10-29 |
1 | 30/10/24 | 2024-10-30 |
2 | 31/10/24 | 2024-10-31 |
한 컬럼씩 뽑기 위해서는 dt
연산자를 반드시 붙여야 함
통째로 뽑은 연도를 컬럼으로 추가하기
dt.day_name()
으로 사용# 0~6번 인덱스 위치에 각 한글 요일 이름이 담긴 리스트
weekday_list = ['월', '화', '수', '목', '금', '토', '일']
# apply 함수로 숫자 -> 요일 이름으로 변환
df['요일'] = df.apply(lambda x : weekday_list[x['weekday']], axis = 1)
df
def를 이용해 함수로 나타낸 코드의 return 값을 모든 데이터프레임에 적용할 수 있음 → apply 함수 이용
전체 데이터프레임이나 특정 칼럼 값을 일괄적으로 가공하는 게 더 빠르겠지만, 특정 조건을 걸어서 조금 더 복잡하게 데이터를 가공해야 할 때 lambda식과 결합하여 apply lambda를 이용함
:
를 기준으로 왼쪽에는 입력 인자들을, 오른쪽에는 계산식(반환되는 return값)을 입력# a와 b의 값을 더하는 get_sum(a,b) 함수
def get_sum(a,b):
return a+b
print(get_sum(10,20))
# 위 식을 lambda식으로 쓰면 한 줄로 작성 가능
get_sum_lambda = lambda x,y : x+y
print(get_sum_lambda(10,20))
a = [10,20,30]
b = [4,5,6]
sums = map(lambda x,y : x+y, a,b)
list(sums)
# 실행 결과: [14, 25, 36]
→ lambda 매개변수 1, 매개변수 2 : 공식, 매개변수 1, 매개변수 2
와 같이 작성
반환값1 if 조건식 else 반환값2
와 같은 형태로 작성해야 한다는 점만 유의해서 사용하면 됨lambda x : 'Child' if x<=18 else 'Adult'
데이터프레임명.apply(lambda x : x['칼럼명'] 반환값
if x['칼럼명'] 조건식
else x['칼럼명'] 반환값),
axis=1)
#1. 바로 lambda식 이용하기. 간단하고 빠르지만, 조건을 많이 걸어야 하는 상황에는 부적합하다.
df['Age_cat1']=df['Age'].apply(lambda x:'Baby'
if x<=4
else ('Child'
if x<=18
else 'Adult'))
print(df['Age_cat1'].value_counts())
df[['Age','Age_cat1']].head()
#2. 함수 만들어서 lambda식 적용하기. 세분화된 분류가 필요한 경우 적절하다.
def Age_cat2(age):
cat2=''
if age<=4 : cat2= 'Baby'
elif age<=18 : cat2= 'Child'
else : cat2 = 'Adult'
return cat2
df['Age_cat2']=df['Age'].apply(lambda x : Age_cat2(x))
print(df['Age_cat2'].value_counts())
df[['Age','Age_cat2']].head()
pd.qcut(data['close_price'], 3).value_counts()
pd.cut(data['close_price'], 3).value_counts()
pd.qcut(data['close_price'], 3, labels = ['L', 'M', 'H'])
pd.cut(data['close_price'], 3, labels = ['L', 'M', 'H'])
data['close_price_group'] = pd.qcut(data['close_price'], 3, labels = ['L', 'M', 'H'])
data[["ticker", "sector", "close_price", "sector_mean", "close_price_group"]]
→ 라벨링한 값은 전체 close_price를 기준으로 그룹지어 라벨링한 것이기 때문에 sector를 기준으로 groupby가 한 번 더 필요
data["price_s_level"] = data.groupby(['sector'])['close_price'].transform(lambda x: pd.qcut(x, 3, labels = ['L', 'M', 'H']))
data[["ticker", "sector", "sector_count", "sector_mean", "close_price", "price_s_level"]]
.transform()
)pd.qcut()
)을 람다 함수(lambda x:)로 수행pandas.cut(x, bins, labels=None, right=True, include_lowest=False, ...)
import pandas as pd
df = pd.DataFrame()
x = np.arange(6)+1
df["x"] = x
df["cut1"] = pd.Series(pd.cut(x, [1,3,5]))
df["cut2"] = pd.Series(pd.cut(x, [-np.inf,1,3,5,np.inf]))
df
x cut1 cut2
0 1 NaN (-inf, 1.0]
1 2 (1.0, 3.0] (1.0, 3.0]
2 3 (1.0, 3.0] (1.0, 3.0]
3 4 (3.0, 5.0] (3.0, 5.0]
4 5 (3.0, 5.0] (3.0, 5.0]
5 6 NaN (5.0, inf]
→ 1과 6의 경우에는 어떤 구간에도 속하지 않으므로 NaN(결측치)으로 표시됨: cut1 열에서 NaN 값이 발생
→ 반면에 cut2 열에서는 구간 경계값을 [-inf, 1, 3, 5, inf]로 지정했으므로 1이하 5초과의 값이 각각 (-inf, 1.0], (5.0, inf]구간에 속하게 됨