아이티윌_데이터 분석 55기/강의내용 필기_Python

#7 7일차_논리연산자/포함연산자, pandas index 설정, pandas 정렬, 벡터화 내장된 문자열 메서드, idxmax / idxmin

ecosso 2026. 5. 19. 16:16

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