01 논리연산자 / 포함연산자
-01 스칼라
-02 여러 개의 논리값에 대한 논리연산자
-03 포함연산자(df.isin)
02 pandas index (index/columns) 설정
-01 index 확인/변경
-02 특정 index 이름 변경(df.rename)
-03 각 index의 이름 변경
-04 특정 index 삭제
03 pandas 정렬
-01 index 정렬
-02 DataFrame 정렬 (값 정렬)
04 벡터화 내장된 문자열 메서드
-01 대소치환
-02 문자열 추출 (문자열 색인)
-03 문자열 분리
-04 문자열 추출
-05 문자열 길이
-06 문자열 포함 횟수
-07 문자열 포함 여부
-08 문자열 결합
-09 문자열 반복
-10 문자열 삽입
05 idxmax / idxmin
01 논리연산자 / 포함연산자
-01 스칼라
v1 = 10
(v1 > 3) and (v1 < 8)
(v1 > 3) or (v1 < 8)
not (v1 > 3)
(v1 > 3) and (v1 < 8)
Out[18]: False
(v1 > 3) or (v1 < 8)
Out[19]: True
not (v1 > 3)
Out[20]: False
-02 여러 개의 논리값에 대한 논리연산자
from pandas import Series, DataFrame
s1 = Series([1,2,3,4,5])
(s1 > 3) and (s1 < 5) # 불가
(s1 > 3) and (s1 < 5)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
~\AppData\Local\Temp\ipykernel_4436\1950858901.py in ?()
----> 1 (s1 > 3) and (s1 < 5)
~\anaconda3\Lib\site-packages\pandas\core\generic.py in ?(self)
1578 @final
1579 def __nonzero__(self) -> NoReturn:
-> 1580 raise ValueError(
1581 f"The truth value of a {type(self).__name__} is ambiguous. "
1582 "Use a.empty, a.bool(), a.item(), a.any() or a.all()."
1583 )
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
(s1 > 3) & (s1 < 5) # 가능 (and => &)
(s1 > 3) | (s1 < 5) # 가능 (or => |)
~(s1 > 3) # 가능 (not => ~)
(s1 > 3) & (s1 < 5)
Out[24]:
0 False
1 False
2 False
3 True
4 False
dtype: bool
(s1 > 3) & (s1 < 5) # 가능 (and => &)
Out[25]:
0 False
1 False
2 False
3 True
4 False
dtype: bool
(s1 > 3) | (s1 < 5) # 가능 (or => |)
Out[26]:
0 True
1 True
2 True
3 True
4 True
dtype: bool
~(s1 > 3) # 가능 (not => ~)
Out[27]:
0 True
1 True
2 True
3 False
4 False
dtype: bool
-03 포함연산자(df.isin)
emp = pd.read_csv('emp.csv')
emp['ENAME'].isin(['SMITH','ALLEN'])
emp.loc[emp['ENAME'].isin(['SMITH','ALLEN']),:]
emp.loc[emp['ENAME'].isin(['SMITH','ALLEN']),:]
Out[29]:
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
0 7369 SMITH CLERK 7902.0 1980-12-17 0:00 800 NaN 20
1 7499 ALLEN SALESMAN 7698.0 1981-02-20 0:00 1600 300.0 30
in sql: where ename in ('SMITH','ALLEN')
in R: emp$ENAME %in% c('SMITH','ALLEN')
ex) emp에서 JOB이 CLERK 또는 SALESMAN이면서 SAL이 1200 이상인 직원의 ENAME, JOB, SAL 출력
emp.loc[emp['JOB'].isin(['CLERK', 'SALESMAN']) & (emp['SAL'] >= 1200),['ENAME','JOB','SAL']]
emp.loc[emp['JOB'].isin(['CLERK', 'SALESMAN']) & (emp['SAL'] >= 1200),['ENAME','JOB','SAL']]
Out[47]:
ENAME JOB SAL
1 ALLEN SALESMAN 1600
2 WARD SALESMAN 1250
4 MARTIN SALESMAN 1250
9 TURNER SALESMAN 1500
13 MILLER CLERK 1300
02 pandas index (index/columns) 설정
-01 index 확인/변경
index를 별도로 지정하지 않은 경우 DataFrame 생성 시 위치값이 자동으로 생성된다.
emp
Out[51]:
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
0 7369 SMITH CLERK 7902.0 1980-12-17 0:00 800 NaN 20
1 7499 ALLEN SALESMAN 7698.0 1981-02-20 0:00 1600 300.0 30
2 7521 WARD SALESMAN 7698.0 1982-02-22 0:00 1250 500.0 30
3 7566 JONES MANAGER 7839.0 1981-04-02 0:00 2975 NaN 20
4 7654 MARTIN SALESMAN 7698.0 1981-09-28 0:00 1250 1400.0 30
5 7698 BLAKE MANAGER 7839.0 1981-05-01 0:00 2850 NaN 30
6 7782 CLARK MANAGER 7839.0 1981-06-09 0:00 2450 NaN 10
7 7788 SCOTT ANALYST 7566.0 1987-04-17 0:00 3000 NaN 20
8 7839 KING PRESIDENT NaN 1981-11-17 0:00 5000 NaN 10
9 7844 TURNER SALESMAN 7698.0 1981-09-08 0:00 1500 0.0 30
10 7876 ADAMS CLERK 7788.0 1987-05-23 0:00 1100 NaN 20
11 7900 JAMES CLERK 7698.0 1981-12-03 0:00 950 NaN 30
12 7902 FORD ANALYST 7566.0 1981-12-03 0:00 3000 NaN 20
13 7934 MILLER CLERK 7782.0 1982-01-23 0:00 1300 NaN 10
1) 각 index 값 확인
emp.index
emp.index
Out[52]: RangeIndex(start=0, stop=14, step=1)
emp.columns
emp.columns
Out[53]: Index(['EMPNO', 'ENAME', 'JOB', 'MGR', 'HIREDATE', 'SAL', 'COMM', 'DEPTNO'], dtype='object')
# index 전체 수정 가능
# 직접 수정
emp.index = emp['EMPNO']
emp.index
Out[55]:
Index([7369, 7499, 7521, 7566, 7654, 7698, 7782, 7788, 7839, 7844, 7876, 7900,
7902, 7934],
dtype='int64', name='EMPNO')
emp
Out[56]:
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
EMPNO
7369 7369 SMITH CLERK 7902.0 1980-12-17 0:00 800 NaN 20
7499 7499 ALLEN SALESMAN 7698.0 1981-02-20 0:00 1600 300.0 30
7521 7521 WARD SALESMAN 7698.0 1982-02-22 0:00 1250 500.0 30
7566 7566 JONES MANAGER 7839.0 1981-04-02 0:00 2975 NaN 20
7654 7654 MARTIN SALESMAN 7698.0 1981-09-28 0:00 1250 1400.0 30
7698 7698 BLAKE MANAGER 7839.0 1981-05-01 0:00 2850 NaN 30
7782 7782 CLARK MANAGER 7839.0 1981-06-09 0:00 2450 NaN 10
7788 7788 SCOTT ANALYST 7566.0 1987-04-17 0:00 3000 NaN 20
7839 7839 KING PRESIDENT NaN 1981-11-17 0:00 5000 NaN 10
7844 7844 TURNER SALESMAN 7698.0 1981-09-08 0:00 1500 0.0 30
7876 7876 ADAMS CLERK 7788.0 1987-05-23 0:00 1100 NaN 20
7900 7900 JAMES CLERK 7698.0 1981-12-03 0:00 950 NaN 30
7902 7902 FORD ANALYST 7566.0 1981-12-03 0:00 3000 NaN 20
7934 7934 MILLER CLERK 7782.0 1982-01-23 0:00 1300 NaN 10
# 특정 컬럼값으로 수정
# 객체 중의 일부 컬럼을 이용하여 index를 덮어쓰는 방법 사용 시 drop 메서드를 사용해야해서 불편함이 있다.
# 따라서 .set_index를 사용하여 df의 특정 컬럼값으로 index 부여 및 해당 컬럼 삭제를 진행하면 편하다.
emp = emp.set_index('EMPNO')
* 단지 index에만 적용되며 컬럼은 직접 수정을 진행해야 한다.
emp
Out[62]:
ENAME JOB MGR HIREDATE SAL COMM DEPTNO
EMPNO
7369 SMITH CLERK 7902.0 1980-12-17 0:00 800 NaN 20
7499 ALLEN SALESMAN 7698.0 1981-02-20 0:00 1600 300.0 30
7521 WARD SALESMAN 7698.0 1982-02-22 0:00 1250 500.0 30
7566 JONES MANAGER 7839.0 1981-04-02 0:00 2975 NaN 20
7654 MARTIN SALESMAN 7698.0 1981-09-28 0:00 1250 1400.0 30
7698 BLAKE MANAGER 7839.0 1981-05-01 0:00 2850 NaN 30
7782 CLARK MANAGER 7839.0 1981-06-09 0:00 2450 NaN 10
7788 SCOTT ANALYST 7566.0 1987-04-17 0:00 3000 NaN 20
7839 KING PRESIDENT NaN 1981-11-17 0:00 5000 NaN 10
7844 TURNER SALESMAN 7698.0 1981-09-08 0:00 1500 0.0 30
7876 ADAMS CLERK 7788.0 1987-05-23 0:00 1100 NaN 20
7900 JAMES CLERK 7698.0 1981-12-03 0:00 950 NaN 30
7902 FORD ANALYST 7566.0 1981-12-03 0:00 3000 NaN 20
7934 MILLER CLERK 7782.0 1982-01-23 0:00 1300 NaN 10
2) 각 index 이름 확인
emp.index.name
emp.index.name
Out[61]: 'EMPNO'
emp.columns.name
emp.columns.name
# index를 다시 데이터프레임의 컬럼으로 재배치
emp.reset_index()
emp.reset_index()
Out[64]:
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
0 7369 SMITH CLERK 7902.0 1980-12-17 0:00 800 NaN 20
1 7499 ALLEN SALESMAN 7698.0 1981-02-20 0:00 1600 300.0 30
2 7521 WARD SALESMAN 7698.0 1982-02-22 0:00 1250 500.0 30
3 7566 JONES MANAGER 7839.0 1981-04-02 0:00 2975 NaN 20
4 7654 MARTIN SALESMAN 7698.0 1981-09-28 0:00 1250 1400.0 30
5 7698 BLAKE MANAGER 7839.0 1981-05-01 0:00 2850 NaN 30
6 7782 CLARK MANAGER 7839.0 1981-06-09 0:00 2450 NaN 10
7 7788 SCOTT ANALYST 7566.0 1987-04-17 0:00 3000 NaN 20
8 7839 KING PRESIDENT NaN 1981-11-17 0:00 5000 NaN 10
9 7844 TURNER SALESMAN 7698.0 1981-09-08 0:00 1500 0.0 30
10 7876 ADAMS CLERK 7788.0 1987-05-23 0:00 1100 NaN 20
11 7900 JAMES CLERK 7698.0 1981-12-03 0:00 950 NaN 30
12 7902 FORD ANALYST 7566.0 1981-12-03 0:00 3000 NaN 20
13 7934 MILLER CLERK 7782.0 1982-01-23 0:00 1300 NaN 10
-02 특정 index 이름 변경(df.rename)
# INDEX의 일부를 직접 수정하는 것은 불가능하다.
emp.columns[4] = 'SALARY'
emp.columns[4] = 'SALARY'
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[66], line 1
----> 1 emp.columns[4] = 'SALARY'
File ~\anaconda3\Lib\site-packages\pandas\core\indexes\base.py:5383, in Index.__setitem__(self, key, value)
5381 @final
5382 def __setitem__(self, key, value) -> None:
-> 5383 raise TypeError("Index does not support mutable operations")
TypeError: Index does not support mutable operations
# 따라서 rename을 사용해야 한다.
emp.rename({'SAL':'SALARY'}, axis=1) # 컬럼 이름 변경
emp.rename({'SAL':'SALARY'}, axis=1)
Out[67]:
ENAME JOB MGR HIREDATE SALARY COMM DEPTNO
EMPNO
7369 SMITH CLERK 7902.0 1980-12-17 0:00 800 NaN 20
7499 ALLEN SALESMAN 7698.0 1981-02-20 0:00 1600 300.0 30
7521 WARD SALESMAN 7698.0 1982-02-22 0:00 1250 500.0 30
7566 JONES MANAGER 7839.0 1981-04-02 0:00 2975 NaN 20
7654 MARTIN SALESMAN 7698.0 1981-09-28 0:00 1250 1400.0 30
7698 BLAKE MANAGER 7839.0 1981-05-01 0:00 2850 NaN 30
7782 CLARK MANAGER 7839.0 1981-06-09 0:00 2450 NaN 10
7788 SCOTT ANALYST 7566.0 1987-04-17 0:00 3000 NaN 20
7839 KING PRESIDENT NaN 1981-11-17 0:00 5000 NaN 10
7844 TURNER SALESMAN 7698.0 1981-09-08 0:00 1500 0.0 30
7876 ADAMS CLERK 7788.0 1987-05-23 0:00 1100 NaN 20
7900 JAMES CLERK 7698.0 1981-12-03 0:00 950 NaN 30
7902 FORD ANALYST 7566.0 1981-12-03 0:00 3000 NaN 20
7934 MILLER CLERK 7782.0 1982-01-23 0:00 1300 NaN 10
emp.rename({7782:1000}, axis=0) # 행 이름 변경
emp.rename({7782:1000}, axis=0)
Out[69]:
ENAME JOB MGR HIREDATE SAL COMM DEPTNO
EMPNO
7369 SMITH CLERK 7902.0 1980-12-17 0:00 800 NaN 20
7499 ALLEN SALESMAN 7698.0 1981-02-20 0:00 1600 300.0 30
7521 WARD SALESMAN 7698.0 1982-02-22 0:00 1250 500.0 30
7566 JONES MANAGER 7839.0 1981-04-02 0:00 2975 NaN 20
7654 MARTIN SALESMAN 7698.0 1981-09-28 0:00 1250 1400.0 30
7698 BLAKE MANAGER 7839.0 1981-05-01 0:00 2850 NaN 30
1000 CLARK MANAGER 7839.0 1981-06-09 0:00 2450 NaN 10
7788 SCOTT ANALYST 7566.0 1987-04-17 0:00 3000 NaN 20
7839 KING PRESIDENT NaN 1981-11-17 0:00 5000 NaN 10
7844 TURNER SALESMAN 7698.0 1981-09-08 0:00 1500 0.0 30
7876 ADAMS CLERK 7788.0 1987-05-23 0:00 1100 NaN 20
7900 JAMES CLERK 7698.0 1981-12-03 0:00 950 NaN 30
7902 FORD ANALYST 7566.0 1981-12-03 0:00 3000 NaN 20
7934 MILLER CLERK 7782.0 1982-01-23 0:00 1300 NaN 10
-03 각 index의 이름 변경
emp.index.name = 'ENO' # 이름 변경
emp.index
Out[74]:
Index([7369, 7499, 7521, 7566, 7654, 7698, 7782, 7788, 7839, 7844, 7876, 7900,
7902, 7934],
dtype='int64', name='ENO')
emp.index.name = None # 이름 삭제
emp.index
Out[76]:
Index([7369, 7499, 7521, 7566, 7654, 7698, 7782, 7788, 7839, 7844, 7876, 7900,
7902, 7934],
dtype='int64')
-04 특정 index 삭제
emp.drop?
Signature:
emp.drop(
labels: 'IndexLabel | None' = None,
*,
axis: 'Axis' = 0,
index: 'IndexLabel | None' = None,
columns: 'IndexLabel | None' = None,
level: 'Level | None' = None,
inplace: 'bool' = False,
errors: 'IgnoreRaise' = 'raise',
) -> 'DataFrame | None'
Docstring:
Drop specified labels from rows or columns.
emp.drop(labels, # 삭제 대상의 이름만 전달 (위치불가)
axis = 0, # 삭제 방향 (0:행, 1:컬럼)
index, # axis 대신 index를 삭제할 때 사용하는 인수
columns, # axis 대신 columns를 삭제할 때 사용하는 인수
level) # 특정 level(multi-index depth) 삭제
emp.drop('JOB', axis=1) # 하나의 컬럼 제거
emp.drop('JOB', axis=1)
Out[78]:
ENAME MGR HIREDATE SAL COMM DEPTNO
7369 SMITH 7902.0 1980-12-17 0:00 800 NaN 20
7499 ALLEN 7698.0 1981-02-20 0:00 1600 300.0 30
7521 WARD 7698.0 1982-02-22 0:00 1250 500.0 30
7566 JONES 7839.0 1981-04-02 0:00 2975 NaN 20
7654 MARTIN 7698.0 1981-09-28 0:00 1250 1400.0 30
7698 BLAKE 7839.0 1981-05-01 0:00 2850 NaN 30
7782 CLARK 7839.0 1981-06-09 0:00 2450 NaN 10
7788 SCOTT 7566.0 1987-04-17 0:00 3000 NaN 20
7839 KING NaN 1981-11-17 0:00 5000 NaN 10
7844 TURNER 7698.0 1981-09-08 0:00 1500 0.0 30
7876 ADAMS 7788.0 1987-05-23 0:00 1100 NaN 20
7900 JAMES 7698.0 1981-12-03 0:00 950 NaN 30
7902 FORD 7566.0 1981-12-03 0:00 3000 NaN 20
7934 MILLER 7782.0 1982-01-23 0:00 1300 NaN 10
emp.drop(columns = ['JOB', 'COMM']) # 여러 컬럼 제거
emp.drop(columns = ['JOB', 'COMM'])
Out[79]:
ENAME MGR HIREDATE SAL DEPTNO
7369 SMITH 7902.0 1980-12-17 0:00 800 20
7499 ALLEN 7698.0 1981-02-20 0:00 1600 30
7521 WARD 7698.0 1982-02-22 0:00 1250 30
7566 JONES 7839.0 1981-04-02 0:00 2975 20
7654 MARTIN 7698.0 1981-09-28 0:00 1250 30
7698 BLAKE 7839.0 1981-05-01 0:00 2850 30
7782 CLARK 7839.0 1981-06-09 0:00 2450 10
7788 SCOTT 7566.0 1987-04-17 0:00 3000 20
7839 KING NaN 1981-11-17 0:00 5000 10
7844 TURNER 7698.0 1981-09-08 0:00 1500 30
7876 ADAMS 7788.0 1987-05-23 0:00 1100 20
7900 JAMES 7698.0 1981-12-03 0:00 950 30
7902 FORD 7566.0 1981-12-03 0:00 3000 20
7934 MILLER 7782.0 1982-01-23 0:00 1300 10
emp.drop([7369, 7499]) # 여러 행 제거
emp.drop([7369, 7499])
Out[80]:
ENAME JOB MGR HIREDATE SAL COMM DEPTNO
7521 WARD SALESMAN 7698.0 1982-02-22 0:00 1250 500.0 30
7566 JONES MANAGER 7839.0 1981-04-02 0:00 2975 NaN 20
7654 MARTIN SALESMAN 7698.0 1981-09-28 0:00 1250 1400.0 30
7698 BLAKE MANAGER 7839.0 1981-05-01 0:00 2850 NaN 30
7782 CLARK MANAGER 7839.0 1981-06-09 0:00 2450 NaN 10
7788 SCOTT ANALYST 7566.0 1987-04-17 0:00 3000 NaN 20
7839 KING PRESIDENT NaN 1981-11-17 0:00 5000 NaN 10
7844 TURNER SALESMAN 7698.0 1981-09-08 0:00 1500 0.0 30
7876 ADAMS CLERK 7788.0 1987-05-23 0:00 1100 NaN 20
7900 JAMES CLERK 7698.0 1981-12-03 0:00 950 NaN 30
7902 FORD ANALYST 7566.0 1981-12-03 0:00 3000 NaN 20
7934 MILLER CLERK 7782.0 1982-01-23 0:00 1300 NaN 10
emp.drop([0,1]) # 이름이 있는 경우는 위치값 전달이 불가능하다.
emp.drop([0,1])
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
Cell In[81], line 1
----> 1 emp.drop([0,1])
File ~\anaconda3\Lib\site-packages\pandas\core\frame.py:5603, in DataFrame.drop(self, labels, axis, index, columns, level, inplace, errors)
5455 def drop(
5456 self,
5457 labels: IndexLabel | None = None,
(...) 5464 errors: IgnoreRaise = "raise",
5465 ) -> DataFrame | None:
5466 """
5467 Drop specified labels from rows or columns.
5468
(...) 5601 weight 1.0 0.8
5602 """
-> 5603 return super().drop(
5604 labels=labels,
5605 axis=axis,
5606 index=index,
5607 columns=columns,
5608 level=level,
5609 inplace=inplace,
5610 errors=errors,
5611 )
File ~\anaconda3\Lib\site-packages\pandas\core\generic.py:4810, in NDFrame.drop(self, labels, axis, index, columns, level, inplace, errors)
4808 for axis, labels in axes.items():
4809 if labels is not None:
-> 4810 obj = obj._drop_axis(labels, axis, level=level, errors=errors)
4812 if inplace:
4813 self._update_inplace(obj)
File ~\anaconda3\Lib\site-packages\pandas\core\generic.py:4852, in NDFrame._drop_axis(self, labels, axis, level, errors, only_slice)
4850 new_axis = axis.drop(labels, level=level, errors=errors)
4851 else:
-> 4852 new_axis = axis.drop(labels, errors=errors)
4853 indexer = axis.get_indexer(new_axis)
4855 # Case for non-unique axis
4856 else:
File ~\anaconda3\Lib\site-packages\pandas\core\indexes\base.py:7136, in Index.drop(self, labels, errors)
7134 if mask.any():
7135 if errors != "ignore":
-> 7136 raise KeyError(f"{labels[mask].tolist()} not found in axis")
7137 indexer = indexer[~mask]
7138 return self.delete(indexer)
KeyError: '[0, 1] not found in axis'
# reset_index()를 사용하면 이와 같은 사용도 가능하다.
emp.groupby('DEPTNO')['SAL'].sum().reset_index()
emp.groupby('DEPTNO')['SAL'].sum().reset_index()
Out[86]:
DEPTNO SAL
0 10 8750
1 20 10875
2 30 9400
ex) academy.csv 파일을 읽고
df = pd.read_csv('academy.csv', encoding = 'cp949')
df.head()
Out[110]:
학생번호 국어점수평균 수학점수평균 영어점수평균 과학점수평균 학업집중도
0 1 90 75 85 60 70
1 2 65 90 60 88 80
2 3 45 53 48 50 60
3 4 77 96 62 92 70
4 5 88 89 80 82 90
1) 학생번호 컬럼을 index로 생성한 후 본문에서 제외
df = df.set_index('학생번호')
df.head()
Out[112]:
국어점수평균 수학점수평균 영어점수평균 과학점수평균 학업집중도
학생번호
1 90 75 85 60 70
2 65 90 60 88 80
3 45 53 48 50 60
4 77 96 62 92 70
5 88 89 80 82 90
2) 학업집중도 컬럼 제거
df = df.drop('학업집중도', axis = 1)
df.head()
Out[114]:
국어점수평균 수학점수평균 영어점수평균 과학점수평균
학생번호
1 90 75 85 60
2 65 90 60 88
3 45 53 48 50
4 77 96 62 92
5 88 89 80 82
3) 컬럼이름을 국어점수평균 -> 국어평균, ..., 과학점수평균 -> 과학평균
'국어점수평균'.replace('점수','')
f1 = lambda x : x.replace('점수','')
df.columns = df.columns.map(f1)
df
df.head()
Out[119]:
국어평균 수학평균 영어평균 과학평균
학생번호
1 90 75 85 60
2 65 90 60 88
3 45 53 48 50
4 77 96 62 92
5 88 89 80 82
+) df.columns = df.columns.map(lambda x : x.replace('점수', '')) 와 동일한 결과를 리턴한다.
+) 또는 df.rename({'국어점수평균':'국어평균', ..., '과학점수평균':'과학평균'}, axis=1) 도 가능하다.
4) 10, 20 학번의 학생 데이터 제거
df = df.drop([10,20], axis=0)
df
Out[121]:
국어평균 수학평균 영어평균 과학평균
학생번호
1 90 75 85 60
2 65 90 60 88
3 45 53 48 50
4 77 96 62 92
5 88 89 80 82
6 90 92 90 96
7 65 70 66 76
8 60 90 70 98
9 46 56 43 55
11 70 93 77 89
12 99 80 95 70
13 97 67 80 60
14 50 40 30 54
15 90 77 92 60
16 55 88 67 92
17 77 90 70 98
18 90 89 80 92
19 76 90 80 92
21 76 75 70 82
22 77 92 68 89
23 60 50 70 40
24 54 70 56 72
25 72 88 67 95
26 58 76 59 80
27 88 60 76 58
28 84 88 90 92
29 45 76 56 78
30 76 54 70 58
31 66 90 70 88
32 88 80 85 88
33 71 48 69 50
34 90 77 82 65
35 34 32 45 50
36 56 78 67 89
37 70 95 72 80
38 93 90 89 91
39 92 97 90 89
40 56 63 70 71
41 88 57 78 60
42 90 92 88 94
43 91 67 89 70
44 58 77 62 88
45 54 50 45 33
46 78 91 77 90
47 92 70 88 60
48 57 76 58 71
49 97 90 96 90
50 69 55 70 54
51 45 56 54 58
52 65 90 70 92
03 pandas 정렬
-01 index 정렬
emp.sort_index(axis=0, # default:index 정렬 (axis=1은 컬럼정렬)
level, # multi-level index의 경우 특정 level 값으로 정렬
ascending = True, # 정렬방식
na_position = 'last', # NA 배치순서 {'first', 'last'}
ignore_index = False) # index 재배치 여부
emp.sort_index(axis=1) # ABC순 정렬
emp.sort_index(axis=1) # ABC순 정렬
Out[138]:
COMM DEPTNO ENAME HIREDATE JOB MGR SAL
7369 NaN 20 SMITH 1980-12-17 0:00 CLERK 7902.0 800
7499 300.0 30 ALLEN 1981-02-20 0:00 SALESMAN 7698.0 1600
7521 500.0 30 WARD 1982-02-22 0:00 SALESMAN 7698.0 1250
7566 NaN 20 JONES 1981-04-02 0:00 MANAGER 7839.0 2975
7654 1400.0 30 MARTIN 1981-09-28 0:00 SALESMAN 7698.0 1250
7698 NaN 30 BLAKE 1981-05-01 0:00 MANAGER 7839.0 2850
7782 NaN 10 CLARK 1981-06-09 0:00 MANAGER 7839.0 2450
7788 NaN 20 SCOTT 1987-04-17 0:00 ANALYST 7566.0 3000
7839 NaN 10 KING 1981-11-17 0:00 PRESIDENT NaN 5000
7844 0.0 30 TURNER 1981-09-08 0:00 SALESMAN 7698.0 1500
7876 NaN 20 ADAMS 1987-05-23 0:00 CLERK 7788.0 1100
7900 NaN 30 JAMES 1981-12-03 0:00 CLERK 7698.0 950
7902 NaN 20 FORD 1981-12-03 0:00 ANALYST 7566.0 3000
7934 NaN 10 MILLER 1982-01-23 0:00 CLERK 7782.0 1300
emp[['JOB','ENAME','MGR','HIREDATE','SAL','COMM']] # 사용자 지정 순서 정렬
emp[['JOB','ENAME','MGR','HIREDATE','SAL','COMM']] # 사용자 지정 순서 정렬
Out[139]:
JOB ENAME MGR HIREDATE SAL COMM
7369 CLERK SMITH 7902.0 1980-12-17 0:00 800 NaN
7499 SALESMAN ALLEN 7698.0 1981-02-20 0:00 1600 300.0
7521 SALESMAN WARD 7698.0 1982-02-22 0:00 1250 500.0
7566 MANAGER JONES 7839.0 1981-04-02 0:00 2975 NaN
7654 SALESMAN MARTIN 7698.0 1981-09-28 0:00 1250 1400.0
7698 MANAGER BLAKE 7839.0 1981-05-01 0:00 2850 NaN
7782 MANAGER CLARK 7839.0 1981-06-09 0:00 2450 NaN
7788 ANALYST SCOTT 7566.0 1987-04-17 0:00 3000 NaN
7839 PRESIDENT KING NaN 1981-11-17 0:00 5000 NaN
7844 SALESMAN TURNER 7698.0 1981-09-08 0:00 1500 0.0
7876 CLERK ADAMS 7788.0 1987-05-23 0:00 1100 NaN
7900 CLERK JAMES 7698.0 1981-12-03 0:00 950 NaN
7902 ANALYST FORD 7566.0 1981-12-03 0:00 3000 NaN
7934 CLERK MILLER 7782.0 1982-01-23 0:00 1300 NaN
emp.sort_index(ascending = False) # 역순 정렬
emp.sort_index(ascending = False) # 역순 정렬
Out[140]:
ENAME JOB MGR HIREDATE SAL COMM DEPTNO
7934 MILLER CLERK 7782.0 1982-01-23 0:00 1300 NaN 10
7902 FORD ANALYST 7566.0 1981-12-03 0:00 3000 NaN 20
7900 JAMES CLERK 7698.0 1981-12-03 0:00 950 NaN 30
7876 ADAMS CLERK 7788.0 1987-05-23 0:00 1100 NaN 20
7844 TURNER SALESMAN 7698.0 1981-09-08 0:00 1500 0.0 30
7839 KING PRESIDENT NaN 1981-11-17 0:00 5000 NaN 10
7788 SCOTT ANALYST 7566.0 1987-04-17 0:00 3000 NaN 20
7782 CLARK MANAGER 7839.0 1981-06-09 0:00 2450 NaN 10
7698 BLAKE MANAGER 7839.0 1981-05-01 0:00 2850 NaN 30
7654 MARTIN SALESMAN 7698.0 1981-09-28 0:00 1250 1400.0 30
7566 JONES MANAGER 7839.0 1981-04-02 0:00 2975 NaN 20
7521 WARD SALESMAN 7698.0 1982-02-22 0:00 1250 500.0 30
7499 ALLEN SALESMAN 7698.0 1981-02-20 0:00 1600 300.0 30
7369 SMITH CLERK 7902.0 1980-12-17 0:00 800 NaN 20
-02 DataFrame 정렬 (값 정렬)
emp.sort_values(by, # 정렬 대상
axis = 0, # 정렬 방향
ascending = True,
na_position = 'last',
ignore_index = False)
ex) 급여순 정렬
emp = pd.read_csv('emp.csv')
emp.sort_values('SAL')
emp.sort_values('SAL')
Out[142]:
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
0 7369 SMITH CLERK 7902.0 1980-12-17 0:00 800 NaN 20
11 7900 JAMES CLERK 7698.0 1981-12-03 0:00 950 NaN 30
10 7876 ADAMS CLERK 7788.0 1987-05-23 0:00 1100 NaN 20
2 7521 WARD SALESMAN 7698.0 1982-02-22 0:00 1250 500.0 30
4 7654 MARTIN SALESMAN 7698.0 1981-09-28 0:00 1250 1400.0 30
13 7934 MILLER CLERK 7782.0 1982-01-23 0:00 1300 NaN 10
9 7844 TURNER SALESMAN 7698.0 1981-09-08 0:00 1500 0.0 30
1 7499 ALLEN SALESMAN 7698.0 1981-02-20 0:00 1600 300.0 30
6 7782 CLARK MANAGER 7839.0 1981-06-09 0:00 2450 NaN 10
5 7698 BLAKE MANAGER 7839.0 1981-05-01 0:00 2850 NaN 30
3 7566 JONES MANAGER 7839.0 1981-04-02 0:00 2975 NaN 20
7 7788 SCOTT ANALYST 7566.0 1987-04-17 0:00 3000 NaN 20
12 7902 FORD ANALYST 7566.0 1981-12-03 0:00 3000 NaN 20
8 7839 KING PRESIDENT NaN 1981-11-17 0:00 5000 NaN 10
# index 재배치 옵션을 넣었을 때의 결과
emp.sort_values('SAL', ignore_index = True)
emp.sort_values('SAL', ignore_index = True)
Out[143]:
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
0 7369 SMITH CLERK 7902.0 1980-12-17 0:00 800 NaN 20
1 7900 JAMES CLERK 7698.0 1981-12-03 0:00 950 NaN 30
2 7876 ADAMS CLERK 7788.0 1987-05-23 0:00 1100 NaN 20
3 7521 WARD SALESMAN 7698.0 1982-02-22 0:00 1250 500.0 30
4 7654 MARTIN SALESMAN 7698.0 1981-09-28 0:00 1250 1400.0 30
5 7934 MILLER CLERK 7782.0 1982-01-23 0:00 1300 NaN 10
6 7844 TURNER SALESMAN 7698.0 1981-09-08 0:00 1500 0.0 30
7 7499 ALLEN SALESMAN 7698.0 1981-02-20 0:00 1600 300.0 30
8 7782 CLARK MANAGER 7839.0 1981-06-09 0:00 2450 NaN 10
9 7698 BLAKE MANAGER 7839.0 1981-05-01 0:00 2850 NaN 30
10 7566 JONES MANAGER 7839.0 1981-04-02 0:00 2975 NaN 20
11 7788 SCOTT ANALYST 7566.0 1987-04-17 0:00 3000 NaN 20
12 7902 FORD ANALYST 7566.0 1981-12-03 0:00 3000 NaN 20
13 7839 KING PRESIDENT NaN 1981-11-17 0:00 5000 NaN 10
ex) 부서번호 순서대로 정렬(오름차순), 부서번호가 같을 때는 급여 역순정렬
emp.sort_values(['DEPTNO', 'SAL'], ascending = [True, False], ignore_index = True)
emp.sort_values(['DEPTNO', 'SAL'], ascending = [True, False], ignore_index = True)
Out[149]:
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
0 7839 KING PRESIDENT NaN 1981-11-17 0:00 5000 NaN 10
1 7782 CLARK MANAGER 7839.0 1981-06-09 0:00 2450 NaN 10
2 7934 MILLER CLERK 7782.0 1982-01-23 0:00 1300 NaN 10
3 7788 SCOTT ANALYST 7566.0 1987-04-17 0:00 3000 NaN 20
4 7902 FORD ANALYST 7566.0 1981-12-03 0:00 3000 NaN 20
5 7566 JONES MANAGER 7839.0 1981-04-02 0:00 2975 NaN 20
6 7876 ADAMS CLERK 7788.0 1987-05-23 0:00 1100 NaN 20
7 7369 SMITH CLERK 7902.0 1980-12-17 0:00 800 NaN 20
8 7698 BLAKE MANAGER 7839.0 1981-05-01 0:00 2850 NaN 30
9 7499 ALLEN SALESMAN 7698.0 1981-02-20 0:00 1600 300.0 30
10 7844 TURNER SALESMAN 7698.0 1981-09-08 0:00 1500 0.0 30
11 7521 WARD SALESMAN 7698.0 1982-02-22 0:00 1250 500.0 30
12 7654 MARTIN SALESMAN 7698.0 1981-09-28 0:00 1250 1400.0 30
13 7900 JAMES CLERK 7698.0 1981-12-03 0:00 950 NaN 30
ex) COMM 오름차순 정렬 (NA를 맨 앞에 배치)
emp.sort_values('COMM') # NA가 마지막에 배치됨 (기본)
emp.sort_values('COMM')
Out[150]:
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
9 7844 TURNER SALESMAN 7698.0 1981-09-08 0:00 1500 0.0 30
1 7499 ALLEN SALESMAN 7698.0 1981-02-20 0:00 1600 300.0 30
2 7521 WARD SALESMAN 7698.0 1982-02-22 0:00 1250 500.0 30
4 7654 MARTIN SALESMAN 7698.0 1981-09-28 0:00 1250 1400.0 30
0 7369 SMITH CLERK 7902.0 1980-12-17 0:00 800 NaN 20
3 7566 JONES MANAGER 7839.0 1981-04-02 0:00 2975 NaN 20
5 7698 BLAKE MANAGER 7839.0 1981-05-01 0:00 2850 NaN 30
6 7782 CLARK MANAGER 7839.0 1981-06-09 0:00 2450 NaN 10
7 7788 SCOTT ANALYST 7566.0 1987-04-17 0:00 3000 NaN 20
8 7839 KING PRESIDENT NaN 1981-11-17 0:00 5000 NaN 10
10 7876 ADAMS CLERK 7788.0 1987-05-23 0:00 1100 NaN 20
11 7900 JAMES CLERK 7698.0 1981-12-03 0:00 950 NaN 30
12 7902 FORD ANALYST 7566.0 1981-12-03 0:00 3000 NaN 20
13 7934 MILLER CLERK 7782.0 1982-01-23 0:00 1300 NaN 10
emp.sort_values('COMM', na_position = 'first') # NA가 먼저 배치됨
emp.sort_values('COMM', na_position = 'first')
Out[151]:
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
0 7369 SMITH CLERK 7902.0 1980-12-17 0:00 800 NaN 20
3 7566 JONES MANAGER 7839.0 1981-04-02 0:00 2975 NaN 20
5 7698 BLAKE MANAGER 7839.0 1981-05-01 0:00 2850 NaN 30
6 7782 CLARK MANAGER 7839.0 1981-06-09 0:00 2450 NaN 10
7 7788 SCOTT ANALYST 7566.0 1987-04-17 0:00 3000 NaN 20
8 7839 KING PRESIDENT NaN 1981-11-17 0:00 5000 NaN 10
10 7876 ADAMS CLERK 7788.0 1987-05-23 0:00 1100 NaN 20
11 7900 JAMES CLERK 7698.0 1981-12-03 0:00 950 NaN 30
12 7902 FORD ANALYST 7566.0 1981-12-03 0:00 3000 NaN 20
13 7934 MILLER CLERK 7782.0 1982-01-23 0:00 1300 NaN 10
9 7844 TURNER SALESMAN 7698.0 1981-09-08 0:00 1500 0.0 30
1 7499 ALLEN SALESMAN 7698.0 1981-02-20 0:00 1600 300.0 30
2 7521 WARD SALESMAN 7698.0 1982-02-22 0:00 1250 500.0 30
4 7654 MARTIN SALESMAN 7698.0 1981-09-28 0:00 1250 1400.0 30
[ 연습문제 ]
df = pd.read_csv('boston_na.csv')
df.info()
1) crim이 큰 순서대로 상위 10%의 tax 평균 출력
df1 = df.sort_values('crim', ascending = False, ignore_index = True)
print(round(df1[0:50]['crim'].mean(), 3))
print(round(df1[0:50]['crim'].mean(), 3))
22.889
# 문제풀이
nrows = int(np.trunc(df.shape[0] * 0.1))
result = df['crim'].sort_values(ascending = False).iloc[:nrows].mean()
print(round(result, 3))
print(round(result, 3))
22.889
2) crim이 큰 순서대로 상위 10%의 tax 평균 출력
a1 = df.sort_values('crim', ascending = False).iloc[:nrows, :]['tax']
print(a1.mean())
print(a1.mean())
666.0
3) medv의 IQR 기준 이상치 수 출력
df1['medv'].describe()
import numpy as np
q3 = np.percentile(df1['medv'], 75)
q1 = np.percentile(df1['medv'], 25)
iqr = q3 - q1
iqr15 = iqr * 1.5
len(df1.loc[df1['medv'] > (q3 + iqr15), :]) + len(df1.loc[df1['medv'] < (q1 - iqr15), :])
len(df1.loc[df1['medv'] > (q3 + iqr15), :]) + len(df1.loc[df1['medv'] < (q1 - iqr15), :])
Out[257]: 40
# 문제풀이
import numpy as np
q1 = np.percentile(df1['medv'], 25)
q3 = np.percentile(df1['medv'], 75)
q1 = df['medv'].quantile(0.25)
q3 = df['medv'].quantile(0.75)
iqr = q3 - q1
result = ((df['medv'] > q3 + iqr * 1.5) | (df['medv'] < q1 - iqr * 1.5)).sum()
print(result)
print(result)
40
04 벡터화 내장된 문자열 메서드
기존 문자열 메서드는 문자상수에만 적용이 가능한 상황이었다.
따라서 Series에서는 map을 통해 원소별 반복을 유도하였다.
그러나 벡터화 내장된 문자열 메서드를 사용하게 되면 map의 사용 없이 자동적으로 원소별 적용이 가능하다.
Series 전용으로 map이 내장되어 있는 개념이며, DataFrame은 호출이 불가능하다.
- s1.str.______
s1 = Series(['1,000','2,000','3,000','4,000'])
s2 = Series(['abc','DEF','XXX','yyy'])
s3 = Series(['abc@naver.com','a1234@gmail.com'])
# 벡터화 내장된 문자열 메서드 목록 확인
dir(s1.str)
dir(s1.str)
Out[269]:
['__annotations__',
'__class__',
'__delattr__',
'__dict__',
'__dir__',
'__doc__',
'__eq__',
...
...
-01 대소치환
s2.upper() # 오류발생
s2.upper()
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
~\AppData\Local\Temp\ipykernel_4436\337354921.py in ?()
----> 1 s2.upper()
~\anaconda3\Lib\site-packages\pandas\core\generic.py in ?(self, name)
6317 and name not in self._accessors
6318 and self._info_axis._can_hold_identifiers_and_holds_name(name)
6319 ):
6320 return self[name]
-> 6321 return object.__getattribute__(self, name)
AttributeError: 'Series' object has no attribute 'upper'
s2.map(lambda x : x.upper()) # 정상적으로 리턴
s2.map(lambda x : x.upper())
Out[271]:
0 ABC
1 DEF
2 XXX
3 YYY
dtype: object
s2.str.upper() # 정상적으로 리턴
s2.str.upper()
Out[272]:
0 ABC
1 DEF
2 XXX
3 YYY
dtype: object
s2.str.lower()
s2.str.lower()
Out[273]:
0 abc
1 def
2 xxx
3 yyy
dtype: object
s2.str.title()
s2.str.title()
Out[274]:
0 Abc
1 Def
2 Xxx
3 Yyy
dtype: object
-02 문자열 추출 (문자열 색인)
s2.str.upper().str[0]
ex) 입사연도 추출
emp = pd.read_csv('emp.csv')
emp['HIREDATE']
emp['HIREDATE']
Out[277]:
0 1980-12-17 0:00
1 1981-02-20 0:00
2 1982-02-22 0:00
3 1981-04-02 0:00
4 1981-09-28 0:00
5 1981-05-01 0:00
6 1981-06-09 0:00
7 1987-04-17 0:00
8 1981-11-17 0:00
9 1981-09-08 0:00
10 1987-05-23 0:00
11 1981-12-03 0:00
12 1981-12-03 0:00
13 1982-01-23 0:00
Name: HIREDATE, dtype: object
emp['HIREDATE'][:4] # 불가 (Series의 4개 원소가 추출됨)\
emp['HIREDATE'][:4]
Out[278]:
0 1980-12-17 0:00
1 1981-02-20 0:00
2 1982-02-22 0:00
3 1981-04-02 0:00
Name: HIREDATE, dtype: object
emp['HIREDATE'].map(lambda x : x[:4]) # map으로 처리
emp['HIREDATE'].map(lambda x : x[:4]) # map으로 처리
Out[279]:
0 1980
1 1981
2 1982
3 1981
4 1981
5 1981
6 1981
7 1987
8 1981
9 1981
10 1987
11 1981
12 1981
13 1982
Name: HIREDATE, dtype: object
emp['HIREDATE'].str[:4]
emp['HIREDATE'].str[:4]
Out[280]:
0 1980
1 1981
2 1982
3 1981
4 1981
5 1981
6 1981
7 1987
8 1981
9 1981
10 1987
11 1981
12 1981
13 1982
Name: HIREDATE, dtype: object
-03 문자열 분리
s3.split('@') # 불가
s3.split('@')
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
~\AppData\Local\Temp\ipykernel_4436\486259454.py in ?()
----> 1 s3.split('@')
~\anaconda3\Lib\site-packages\pandas\core\generic.py in ?(self, name)
6317 and name not in self._accessors
6318 and self._info_axis._can_hold_identifiers_and_holds_name(name)
6319 ):
6320 return self[name]
-> 6321 return object.__getattribute__(self, name)
AttributeError: 'Series' object has no attribute 'split'
s3.map(lambda x : x.split('@')[0]) # map으로 처리
s3.map(lambda x : x.split('@')[0]) # map으로 처리
Out[284]:
0 abc
1 a1234
dtype: object
s3.str.split('@').str[0] # Series 내 원소별 추출이기 때문에 .str[0]을 붙인다.
s3.str.split('@').str[0] # Series 내 원소별 추출이기 때문에 .str[0]을 붙인다.
Out[292]:
0 abc
1 a1234
dtype: object
-04 문자열 추출
s1.replace(',','') # 삭제 불가 (값치환 메서드로 해석되었기 때문)
s1.replace(',','')
Out[297]:
0 1,000
1 2,000
2 3,000
3 4,000
dtype: object
s1.map(lambda x : x.replace(',','')) # map으로 처리
s1.map(lambda x : x.replace(',',''))
Out[295]:
0 1000
1 2000
2 3000
3 4000
dtype: object
s1.str.replace(',','')
s1.str.replace(',','')
Out[296]:
0 1000
1 2000
2 3000
3 4000
dtype: object
+) 정수로의 변환을 원한다면 s1.str.replace(',','').astype('int')
-05 문자열 길이
len(s1) # Series의 원소의 수
len(s1)
Out[299]: 4
s1.str.len() # Series의 각 원소별 문자열 크기
s1.str.len()
Out[300]:
0 5
1 5
2 5
3 5
dtype: int64
-06 문자열 포함 횟수
s2.count('y') # 불가
s2.count('y')
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[302], line 1
----> 1 s2.count('y')
TypeError: Series.count() takes 1 positional argument but 2 were given
s2.str.count('y') # 가능
s2.str.count('y')
Out[303]:
0 0
1 0
2 0
3 3
dtype: int64
-07 문자열 포함 여부
'a' in 'abcd' # 문자열에 'a'가 포함되어 있는지에 대한 여부 확인
'a' in 'abcd'
Out[304]: True
'abc' in list(s2) # 원소 중 하나가 'abc'를 포함하고 있는지에 대한 여부 확인
'abc' in list(s2)
Out[307]: True
=> 문자열의 각각에 대한 처리가 불가능하다.
s2.map(lambda x : 'a' in x) # Series의 각 원소별로 문자열 'a'를 포함하는지 여부
s2.map(lambda x : 'a' in x)
Out[308]:
0 True
1 False
2 False
3 False
dtype: bool
s2.str.contains('a') # Series의 각 원소별로 문자열 'a'를 포함하는지 여부
s2.str.contains('a')
Out[309]:
0 True
1 False
2 False
3 False
dtype: bool
[ 연습문제 ]
card = pd.read_csv('card_history.csv', encoding = 'cp949')
1) NUM 컬럼을 INDEX에 배치
card = card.set_index('NUM')
2) 식료품 지출 총합
card['식료품'] = card['식료품'].str.replace(',','').astype('int')
card['식료품'].sum()
card['식료품'].sum()
Out[352]: np.int64(795500)
3) 각 지출항목별 지출 총합
card.str.replace(',','').astype('int') # 오류발생
card.str.replace(',','').astype('int')
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
~\AppData\Local\Temp\ipykernel_4436\3575258394.py in ?()
----> 1 card.str.replace(',','').astype('int')
~\anaconda3\Lib\site-packages\pandas\core\generic.py in ?(self, name)
6317 and name not in self._accessors
6318 and self._info_axis._can_hold_identifiers_and_holds_name(name)
6319 ):
6320 return self[name]
-> 6321 return object.__getattribute__(self, name)
AttributeError: 'DataFrame' object has no attribute 'str'
▲ 1차원에 해당되는 데이터만 처리가 가능하다보니 DataFrame에는 사용할 수 없다.
(1) 각 컬럼마다 변경
card['식료품'] = card['식료품'].str.replace(',','').astype('int')
card['의복'] = card['의복'].str.replace(',','').astype('int')
card['외식비'] = card['외식비'].str.replace(',','').astype('int')
card['책값'] = card['책값'].str.replace(',','').astype('int')
card['온라인소액결제'] = card['온라인소액결제'].str.replace(',','').astype('int')
card['의료비'] = card['의료비'].str.replace(',','').astype('int')
(2) applymap 사용
card = card.applymap(lambda x : x.replace(',','')).astype(int)
card
Out[366]:
식료품 의복 외식비 책값 온라인소액결제 의료비
NUM
1 19400 143000 8600 29000 5600 19200
2 22200 120400 7000 26000 3300 13000
3 24600 88500 7500 22000 7500 16600
4 22300 124800 7700 78000 3900 28100
5 31800 130100 8400 25000 7700 20500
6 43000 118200 6300 25000 4300 32500
7 29400 147600 10700 24000 12000 26500
8 29200 161900 7500 33000 6300 3500
9 29100 134900 4600 27000 7300 18700
10 24000 136100 8100 32000 6600 24400
11 30100 139600 7500 23000 7300 27300
12 13500 141500 7800 25000 2900 22300
13 24000 132600 6700 28000 7000 28800
14 20600 105600 32000 21000 6200 41000
15 20600 153500 6700 27000 3100 19100
16 28500 118500 8200 25000 6000 25800
17 22900 69100 6700 33000 6900 14600
18 26400 230000 8800 24000 7500 19600
19 24200 47500 8900 21000 4900 11100
20 28600 127000 9800 23000 3700 4500
21 21700 110400 6500 28000 5600 25500
22 34500 123900 8200 134000 6000 27900
23 21700 124300 42000 21000 13000 15000
24 27400 112400 3800 24000 5800 21300
25 25400 253000 6200 27000 5700 26000
26 28600 139300 7100 33000 6000 21800
27 38100 122900 6000 26000 6800 22400
28 27800 134200 8600 21000 7200 17400
29 31300 93800 6600 30000 5400 29200
30 24600 163100 6900 30000 4800 10000
card.sum()
card.sum()
Out[367]:
식료품 795500
의복 3947700
외식비 281400
책값 945000
온라인소액결제 186300
의료비 633600
dtype: int64
4) 각 지출항목별 지출 총합을 구하고 지출 총합이 가장 큰 지출항목 출력
card.sum().idxmax()
card.sum().idxmax()
Out[369]: '의복'
> df.idxmax() : 최댓값을 가지는 인덱스 리턴
> df.idxmin() : 최솟값을 가지는 인덱스 리턴
-08 문자열 결합
-08 문자열 결합
'a' + 'b'
'a' + 'b'
Out[370]: 'ab'
1) 하나의 Series에 대한 내부 결합
s4 = Series([['a','b'],['c','d'],['e','f']])
시리즈의 각 원소가 다중값을 가지고 있는 상황이다.
s4
Out[372]:
0 [a, b]
1 [c, d]
2 [e, f]
dtype: object
s4.str.join(sep='-') # sep 전달 필수 (생략 시 에러 발생)
# Series의 원소 내부 결합
s4.str.join(sep='-')
Out[374]:
0 a-b
1 c-d
2 e-f
dtype: object
s2
s2
Out[376]:
0 abc
1 DEF
2 XXX
3 yyy
dtype: object
s2.str.cat(sep='-') # Series의 모든 원소를 결합하여 하나의 문자열로 리턴 (sep 생략 가능)
'-'.join(s2) # 위와 동일한 결과를 리턴
s2.str.cat(sep='-') # Series의 모든 원소를 결합
Out[378]: 'abc-DEF-XXX-yyy'
'-'.join(s2)
Out[379]: 'abc-DEF-XXX-yyy'
2) 여러 Series 결합
year = Series(['2024','2025','2026'])
month = Series(['01','02','03'])
year + '/' + month
year + '/' + month
Out[385]:
0 2024/01
1 2025/02
2 2026/03
dtype: object
-09 문자열 반복
'a' * 10
'a' * 10
Out[380]: 'aaaaaaaaaa'
s2 * 5
s2 * 5
Out[381]:
0 abcabcabcabcabc
1 DEFDEFDEFDEFDEF
2 XXXXXXXXXXXXXXX
3 yyyyyyyyyyyyyyy
dtype: object
s2.str.repeat(5) # 위와 동일
s2.str.repeat(5)
Out[382]:
0 abcabcabcabcabc
1 DEFDEFDEFDEFDEF
2 XXXXXXXXXXXXXXX
3 yyyyyyyyyyyyyyy
dtype: object
-10 문자열 삽입
1) zfill
'2'.zfill(2)
'2'.zfill(2)
Out[386]: '02'
month = Series(['1','2','3'])
month.str.zfill(2)
month.str.zfill(2)
Out[389]:
0 01
1 02
2 03
dtype: object
2) rjust, ljust
'a'.rjust(10,'*')
'a'.ljust(10,'*')
'a'.rjust(10,'*')
Out[391]: '*********a'
'a'.ljust(10,'*')
Out[392]: 'a*********'
month.str.rjust(2,'0')
month.str.rjust(2,'0')
Out[393]:
0 01
1 02
2 03
dtype: object
3) str.pad
month.str.pad(2, fillchar = '0')
month.str.pad(2, fillchar = '0')
Out[396]:
0 01
1 02
2 03
dtype: object
[ 연습문제 ]
movie_ex1.csv 파일을 읽고
movie = pd.read_csv('movie_ex1.csv', encoding = 'cp949')
movie.head()
Out[399]:
년 월 일 지역-시도 지역-시군구 지역-읍면동 성별 연령대 이용_비율(%)
0 2018 2 1 강원도 강릉시 임당동 여 50대 0.00016
1 2018 2 1 강원도 강릉시 임당동 남 30대 0.00165
2 2018 2 1 강원도 강릉시 임당동 남 50대 0.00049
3 2018 2 1 강원도 속초시 조양동 남 40대 0.00148
4 2018 2 1 강원도 속초시 조양동 남 50대 0.00008
1) 날짜컬럼 생성(2018/02/01) 형태로 변환하여 저장, 기존 년,월,일 컬럼은 제거
f1 = lambda x, y, z: str(x) + '/' + str(y) + '/' + str(z)
movie['날짜'] = list(map(f1, movie['년'], movie['월'], movie['일']))
movie = movie.iloc[:, 3:]
movie
Out[447]:
지역-시도 지역-시군구 지역-읍면동 성별 연령대 이용_비율(%) 날짜
0 강원도 강릉시 임당동 여 50대 0.00016 2018/2/1
1 강원도 강릉시 임당동 남 30대 0.00165 2018/2/1
2 강원도 강릉시 임당동 남 50대 0.00049 2018/2/1
3 강원도 속초시 조양동 남 40대 0.00148 2018/2/1
4 강원도 속초시 조양동 남 50대 0.00008 2018/2/1
... ... ... .. ... ... ...
66865 충청북도 충주시 문화동 여 30대 0.00016 2018/2/28
66866 충청북도 청주시 청원구 오창읍 여 50대 0.00025 2018/2/28
66867 충청북도 청주시 흥덕구 향정동 남 50대 0.00049 2018/2/28
66868 충청북도 충주시 문화동 여 40대 0.00049 2018/2/28
66869 충청북도 충주시 문화동 여 50대 0.00058 2018/2/28
# 문제풀이
movie['날짜'] = (movie['년'].astype(str) + '/' + movie['월'].astype(str).str.zfill(2) + '/' + movie['일'].astype(str).str.zfill(2))
movie = movie.drop(['년','월','일'], axis = 1).sort_index(axis=1)
2) 연령대를 '대' 제거 후 숫자로 변환
movie['연령대'] = movie['연령대'].str.replace('대','').str.replace('이상','').astype('int')
movie
Out[449]:
지역-시도 지역-시군구 지역-읍면동 성별 연령대 이용_비율(%) 날짜
0 강원도 강릉시 임당동 여 50 0.00016 2018/2/1
1 강원도 강릉시 임당동 남 30 0.00165 2018/2/1
2 강원도 강릉시 임당동 남 50 0.00049 2018/2/1
3 강원도 속초시 조양동 남 40 0.00148 2018/2/1
4 강원도 속초시 조양동 남 50 0.00008 2018/2/1
... ... ... .. ... ... ...
66865 충청북도 충주시 문화동 여 30 0.00016 2018/2/28
66866 충청북도 청주시 청원구 오창읍 여 50 0.00025 2018/2/28
66867 충청북도 청주시 흥덕구 향정동 남 50 0.00049 2018/2/28
66868 충청북도 충주시 문화동 여 40 0.00049 2018/2/28
66869 충청북도 충주시 문화동 여 50 0.00058 2018/2/28
# 문제풀이
movie['연령대'] = movie['연령대'].str[:2].astype(int)
3) 서울시에서 영화이용률 총합이 가장 큰 구 확인
movie2 = movie.groupby(['지역-시도','지역-시군구'])['이용_비율(%)'].sum().reset_index()
movie3 = movie2.loc[movie2['이용_비율(%)'] == movie2.groupby('지역-시도')['이용_비율(%)'].transform('max'), : ]
result1 = movie3.loc[movie3['지역-시도'] == '서울특별시','지역-시군구'].iloc[0]
result2 = movie3.loc[movie3['지역-시도'] == '서울특별시', '이용_비율(%)'].iloc[0]
print(result1)
print(result2)
print(result1)
강남구
print(result2)
5.51883
05 idxmax / idxmin
최대 / 최소를 가지는 index를 리턴하는 메서드
df.idxmax(axis = 0,
skipna = True)
ex) 아래 카드 지출 내역을 토대로 각 지출항목별 지출이 가장 많은 날짜 출력
card = pd.read_csv('card_history.csv', encoding = 'cp949')
card = card.set_index('NUM')
card = card.applymap(lambda x : x.replace(',','')).astype(int)
card.head()
Out[496]:
식료품 의복 외식비 책값 온라인소액결제 의료비
NUM
1 19400 143000 8600 29000 5600 19200
2 22200 120400 7000 26000 3300 13000
3 24600 88500 7500 22000 7500 16600
4 22300 124800 7700 78000 3900 28100
5 31800 130100 8400 25000 7700 20500
card.idxmax()
card.idxmax()
Out[494]:
식료품 6
의복 25
외식비 23
책값 22
온라인소액결제 23
의료비 14
dtype: int64
ex) 각 일자별로 지출이 가장 많은 품목
card.idxmax(axis=1)
card.idxmax(axis=1)
Out[497]:
NUM
1 의복
2 의복
3 의복
4 의복
5 의복
6 의복
7 의복
8 의복
9 의복
10 의복
11 의복
12 의복
13 의복
14 의복
15 의복
16 의복
17 의복
18 의복
19 의복
20 의복
21 의복
22 책값
23 의복
24 의복
25 의복
26 의복
27 의복
28 의복
29 의복
30 의복
dtype: object
ex) emp에서 급여가 가장 높은 사번 출력
emp = emp.set_index('EMPNO')
emp['SAL'].idxmax()
emp['SAL'].idxmax()
Out[499]: np.int64(7839)
[ 연습문제 ]
df = pd.read_csv('academy.csv', encoding = 'cp949')
df = df.set_index('학생번호')
df.head()
Out[570]:
국어점수평균 수학점수평균 영어점수평균 과학점수평균 학업집중도
학생번호
1 90 75 85 60 70
2 65 90 60 88 80
3 45 53 48 50 60
4 77 96 62 92 70
5 88 89 80 82 90
1) 국어점수평균이 가장 높은 학생 번호 출력
result1 = df['국어점수평균'].idxmax()
print(result1)
print(result1)
12
2) 각 학생별로 가장 성적이 높은 과목 출력
result2 = df.idxmax(axis=1).mode().iloc[0]
print(result2)
print(result2)
과학점수평균
3) 총 점수 기준으로 점수가 가장 높은 상위 5명의 총 점수 평균 출력
# 총점수 = 국어 + 수학 + 영어 + 과학 + 학업집중도 * 0.1
total = df.drop(columns = '학업집중도').sum(axis=1) + df['학업집중도'] * 0.1
result3 = total.sort_values(ascending = False).iloc[:5].mean()
print(result3)
print(result3)
376.2
'아이티윌_데이터 분석 55기 > 강의내용 필기_Python' 카테고리의 다른 글
| #9 9일차_ multi - level index 실습 (0) | 2026.05.21 |
|---|---|
| #8 8일차_빈도수 / 유일값 확인, 중복값 처리, shift, multi-level index (0) | 2026.05.20 |
| #6 6일차_pd의 행·열 결합 / 수학 및 통계 함수·메서드 / 결측치 처리 (0) | 2026.05.18 |
| #5 5일차_형 변환 함수/매서드, SQL사용, DB 연동, array (0) | 2026.05.15 |
| #4 4일차_사용자 정의함수, groupby 연산, 조인 (0) | 2026.05.14 |