본문 바로가기
목차
파이썬

[파이썬]python pandas 전처리 공부

by 지각생 2022. 4. 22.
728x90

import pandas as pd

 

판다스 2가지 타입 존재

series

데이터 구조가 index-value

 

 

dataframe

index-column-value


시리즈는 

data의 순서를 나타내는 판다스의 데이터 자료형이다.

인덱스에 값 주기

s1 = pd.Series([10,20,30,40])

합 구하기

s1.sum()

평균 구하기

s1.mean()

 

인덱스에 별칭 지어서 값 매겨 주고 Name 지어주기

s2 = pd.Series(['분식이','쏘니'],index=['하나','둘'], name='출석부')

 

딕셔너리 이용해서 위와 같이 만들기

 

딕셔너리 변수 만들어서 시리즈에 넣기 (즉 딕셔너리나 리스트를 이용해서 시리즈 만들 수 있다)

 

시리즈는 순서가 있는 인덱싱 구조이다.

 

인덱스가 글씨여도 대괄호 이용하여 밸류값 출력

 

특정 범위 출력

 

값으로 인덱싱 찾기

 

위 True ,  False로 인덱싱

 

DataFrame

시리즈에서 컬럼이라는 항목만 붙은채로 사용가능.

 

데이터 프레임의 컬럼

 

데이터 프레임을 다중 리스트 구조

 

 

컬럼명 붙이기, df1=pd.DataFrame([[ ],[ ]], columns=[' ', ' '])

 

전체 data 중 특정 컬럼 가져오기

가져온 특정 컬럼 중에서 sum, mean 등 합계 평균 구할 수 있음

위에 예시는 [] 한번 시 series형태이고 [[]] 대괄 호 2번시 DataFrame형태임.

오류 유발 문법

 

위 오류 문법은 대괄호 2번 해서 컬럼이 나올 수 있도록 해야한다

실무 분석 2탄

DataFrame 정리

  

pd.read_csv

 

객체.shape

(전체 갯수, 컬럼 갯수)

 

객체.info()

객체.describe()

숫자만 뽑아서 

5 number summary 뽑아줌

 

5 number summary란

: min, 25%, 50%, 75%, max ,mean, std, count 를 뽑아줌

 

min 구매수량에 -값이 있는걸 보고는 잘못된 data구나 라고 알 수 있음.

 

객체.head() / 객체.tail()

상위 5개

가장 마지막부터해서 5개

 

객체.isnull()

True : data가 미존재. (missing 된 data가 있다)

False : data가 존재. (missing 된 data가 없다)

 

객체.isnull().sum()

 

객체.columns

 

 

데이터 추출

df1['구매금액']

시리즈 형태로 data 출력

 

df1['구매금액'].sum()

df1['구매금액'].describe()

 

df1[[' 구매금액','성별']]

 

df2 = df1[[' 구매금액','성별']]

처럼 변수에 객체 담을 수 있다

 

데이터 분석 3탄

객체.iloc[index]

행단위 데이터 추출

 

 

객체.iloc[-1]

맨 뒤의 정보 추출

(-1이면 가장 마지막 인덱스 번호이다. 역순 조회시 음수값)

 

객체.iloc[0:11]

0번째 까지 10번 까지

 

데이터 정렬

객체.sort_values(by='구매금액')

기본값은 오름차순

내림 차순으로 하고 싶으면

객체.sort_values(by='구매금액', ascending=False)

 

객체.sort_values(by=['구매수량', '연령'], ascending=[False, True]).iloc[:10]

 

데이터 필터

객체.value_counts()

객체 ==  '40대'

df1.loc[cond1]

cond1에는 40대와 일치하는 내용이면 true값이 들어 있는데

그걸 .loc[]를 사용하면

40대에 해당하는 내용만 출력됨.

 

df1.loc[cond1].shape

 

df1.loc[cond1 & cond2]

 

연습

  • 30대 여성 추출 -> 구매금액 높은순서로 정렬
  • 파일로 저장

인코딩 = cp949는 한글을 지원해주는 인코딩

 

엑셀 데이터 전처리 쉽게하기

정형 데이터(관계데이터) : 엑셀 데이터 같은 거

비정형 데이터 : 이미지, 소리, 시그널 같은 거

 

여기선 정형데이터를 주로 다룰 것임.

 

정형 데이터 : 행, 열 , 값 중요

 

 

문자형 데이터냐 수치형데이터냐를 구분해서 보자

 

 

df1['카테고리'].unique()

 

df1['카테고리'].value_counts()

df1[object_list]

object_list = list(set(total_list)-set(numeric_list))

 

df1[object_list].describe()

[Pandas] loc[ ] 로 행, 열 조회하기

Pandas(판다스, 팬더스) Dataframe(2차원, 행열)에서

loc를 이용해서 행 또는 열의 데이터를 조회하는 방법에 대해 알아보겠습니다.

loc는 소괄호()가 아닌 대괄호[]로 감쌉니다.

loc의 첫번째는 행에 대한 정보, 두번째는 열에 대한 정보를 입력합니다.

실습을 통해 알아보겠습니다.

판다스 모듈을 가져오고 실습할 1~5월의 매출액, 영업이익, 순이익 데이터를 만듭니다.

1) 행 조회하기

행을 조회하기 위해서 행명(인덱스명)을 입력합니다.

배열형태가 아닌 값을 입력하면 1차원 시리즈 형태가 리턴됩니다.

배열형태를 입력하면 2차원 데이터프레임 형태가 리턴됩니다.

여러 행명(인덱스명)를 입력하여 여러 행을 가져올 수 있습니다.

특정 행만 제외하고 가져올 수도 있습니다. 2월만 제외시켜보겠습니다.

인덱싱으로 1월부터 연속해서 4월까지 행을 가져올 수 있습니다.

인덱스 개수와 동일한 True/False의 배열을 지정해 True인 행만 가져올 수 있습니다.

2) 열 조회하기

모든 행은 :로 표시하고 쉼표(,)를 입력하고 열명을 입력하면 해당 열만 가져옵니다.

배열행태가 아닌 값을 입력하면 1차원 시리즈 형태가 리턴됩니다.

배열형태로 열명을 입력하면 2차원 데이터프레임 형태가 리턴됩니다.

특정 열(=컬럼)만 제외하고 가져올 수 있습니다. 매출액을 제외한 나머지 열을 모두 가져옵니다.

인덱싱으로 매출액 컬럼부터 연속해서 순이익컬럼까지의 열을 가져올 수 있습니다. (열의 순서 따름)

열 개수와 동일한 True/False의 배열을 지정해 True인 열만 가져올 수 있습니다.

3) 행과 열 조회하기

마지막으로 행과 열 정보를 동시에 지정해서 가져올 수 있습니다.

행과 열 모두 배열 형태가 아닌 값을 입력한 경우 실제 값 1개만 리턴됩니다.

이번에는 행과 열 모두 배열 형태로 입력해보겠습니다.

2차원의 데이터프레임이 리턴됩니다.

끝.

loc[ ] 를 더 자세히 알아보고 싶다면 아래 링크를 참고하세요.

 

https://m.blog.naver.com/wideeyed/221964700554

 

[Pandas] loc[ ] 로 행, 열 조회하기

Pandas(판다스, 팬더스) Dataframe(2차원, 행열)에서 loc를 이용해서 행 또는 열의 데이터를 조회하는 방...

blog.naver.com

 

DataFrame 내의 열을 이용한 인덱스 설정 (set_index 메서드)

DataFrame에는 set_index() 메서드를 적용할 수 있다.

  ○ 이 메서드는 열의 레이블(label) 혹은 열 레이블의 리스트(MultiIndex를 작성할 경우)을 입력받는다.

set_index 메서드는 아래와 같이 사용할 수 있다.

 

set_index 메서드 사용형식)

DataFrame.set_index(keys, drop=True, append=False, inplace=False)

 

keys는 인덱스로 세팅하려하는 열의 레이블을 입력받는다. 

  ○ 멀티인덱스의 경우 레이블의 배열을 입력받는다.

drop은 인덱스로 세팅한 열을 DataFrame내에서 삭제할지 여부를 결정한다. (선택적 입력 가능)

append는 기존에 존재하던 인덱스를 삭제할지 여부를 결정한다. (선택적 입력 가능)

inplace는 원본 객체를 변경할지 여부를 결정한다. (선택적 입력 가능)

 

set_index를 통해 DataFrame의 인덱스를 설정하는 예제는 다음과 같다.

 

set_index 메서드 사용 예)

# pandas와 numpy의 import

In[2]: import pandas as pd

In[3]: import numpy as np

 

# 예제용 배열 선언

In[9]: ex_df=pd.DataFrame([[0,1,2,'r0'],[3,4,5,'r1'],[6,7,8,'r2']], columns=['c0','c1','c2','c4'])

In[10]: ex_df

Out[10]: 

   c0  c1  c2  c4

0   0   1   2  r0

1   3   4   5  r1

2   6   7   8  r2

 

# set_index 메서드의 적용

In[11]: ex_df.set_index('c4')

Out[11]: 

    c0  c1  c2

c4            

r0   0   1   2

r1   3   4   5

r2   6   7   8

 

drop 입력인자는 사용자에게 인덱스 세팅에 사용한 열을 삭제할 것인지 혹은 유지를 결정할 수 있게 해준다.

append 입력인자는 사용자에게 기존에 존재하는 인덱스를 유지시키고 새로운 인덱스를 추가할 것인지 여부를 결정해준다.

  ○ MultiIndex에도 마찬가지로 새로운 인덱스를 추가할 것인지 여부를 결정할 수 있게 해준다.

inplace는 여러 메서드들과 마찬가지로 원본 데이터를 변경할 것인지 복사본을 반환할 것인지 여부를 결정한다.

 

각 인자에 대한 사용 예제는 다음과 같다.

 

set_index의 입력변수 사용 예)

# pandas와 numpy의 import

In[2]: import pandas as pd

In[3]: import numpy as np

 

# 예제용 배열 선언

In[12]: ex_df.set_index('c4',drop=False)

Out[12]: 

    c0  c1  c2  c4

c4                

r0   0   1   2  r0

r1   3   4   5  r1

r2   6   7   8  r2

 

# append 입력변수 사용

In[13]: ex_df.set_index('c4',append=True)

Out[13]: 

      c0  c1  c2

  c4            

0 r0   0   1   2

1 r1   3   4   5

2 r2   6   7   8

In[14]: ex_df       # inplace입력변수가 기본값으로 False이므로 원본 객체 변경되지 않음

Out[14]: 

   c0  c1  c2  c4

0   0   1   2  r0

1   3   4   5  r1

2   6   7   8  r2

 

# inplace입력변수 사용

In[15]: ex_df.set_index('c4',inplace=True)

In[16]: ex_df

Out[16]: 

    c0  c1  c2

c4            

r0   0   1   2

r1   3   4   5

r2   6   7   8

 

중복된 행 개수 구하기

출처:https://yogyui.tistory.com/entry/pandas-%EC%A4%91%EB%B3%B5%EB%90%9C-%EC%9A%94%EC%86%8C-%EB%84%98%EB%B2%84%EB%A7%81%ED%95%98%EA%B8%B0

 

간단하게 가상의 구매 목록을 하나 만들어주자

from datetime import date
import pandas as pd

df = pd.DataFrame([
    {'구매일': date(2021,12,1), '품목': '계란', '수량': 1, '가격': 3000},
    {'구매일': date(2021,12,1), '품목': '라면', '수량': 1, '가격': 1000},
    {'구매일': date(2021,12,1), '품목': '우유', '수량': 2, '가격': 2500},
    {'구매일': date(2021,12,4), '품목': '케찹', '수량': 1, '가격': 2000},
    {'구매일': date(2021,12,4), '품목': '마요네즈', '수량': 1, '가격': 2000},
    {'구매일': date(2021,12,5), '품목': '두부', '수량': 1, '가격': 1000},
    {'구매일': date(2021,12,8), '품목': '쌀', '수량': 1, '가격': 10000},
    {'구매일': date(2021,12,8), '품목': '고추장', '수량': 1, '가격': 4000},
    {'구매일': date(2021,12,8), '품목': '된장', '수량': 1, '가격': 3500},
    {'구매일': date(2021,12,8), '품목': '커피', '수량': 1, '가격': 20000},
    {'구매일': date(2021,12,10), '품목': '콜라', '수량': 1, '가격': 1000},
    {'구매일': date(2021,12,10), '품목': '사이다', '수량': 1, '가격': 1000}
])
df = df[['구매일', '품목', '수량', '가격']]
In [1]:df
Out[1]: 
           구매일    품목  수량    가격
0   2021-12-01    계란   1  3000
1   2021-12-01    라면   1  1000
2   2021-12-01    우유   2  2500
3   2021-12-04    케찹   1  2000
4   2021-12-04  마요네즈   1  2000
5   2021-12-05    두부   1  1000
6   2021-12-08    계란   1  3000
7   2021-12-08    계란   1  3000
8   2021-12-08    계란   1  3000
9   2021-12-08    계란   1  3000
10  2021-12-10    계란   1  3000
11  2021-12-10    계란   1  3000

여기서는 집계된 그룹들의 개수를 합산하기 위해 count 메서드를 호출하면 

In [7]: df.groupby('구매일').count()
Out[7]: 
            품목  수량  가격
구매일                   
2021-12-01   3   3   3
2021-12-04   2   2   2
2021-12-05   1   1   1
2021-12-08   4   4   4
2021-12-10   2   2   2

구매일을 기준으로 각 열별로 레코드가 몇 개씩인지를 합산해준다 (SQL GROUP BY COUNT랑 동일)

In [8]: df.groupby('구매일').count()[df.columns[1]]
Out[8]: 
구매일
2021-12-01    3
2021-12-04    2
2021-12-05    1
2021-12-08    4
2021-12-10    2
Name: 품목, dtype: int64

 

파이썬 코드 분석

os.listdir(경로) & . remove(값) 

import os

folder_dir = 'D:/VScodeWorkspace/python'
folder_list = os.listdir(folder_dir)

if 'data1.txt' in folder_list:
    folder_list.remove('data1.txt')

for folder_name in folder_list:
    print(folder_name)
  • listdir은 폴더랑 파일 모두 찾는다.
  • .remove 함수를 쓰면 리스트 안에 값만 지운다(파일이나 폴더를 지우는건 아님)

 

출력

practice_file_code11-01.py
practice_file_code11-04.py
practice_file_code11-06.py
practice_file_data_check.py
practice_file_data_check_test.py
text.txt
연습

폴더

 

os.walk(경로)

import os

folder_dir = 'D:/VScodeWorkspace/python'

for dirName, subDirList, fnames in os.walk(folder_dir):

  for fname in fnames :
    print(os.path.join(dirName,fname))

출력

D:/VScodeWorkspace/python\data1.txt
D:/VScodeWorkspace/python\practice_file_code11-01.py
D:/VScodeWorkspace/python\practice_file_code11-04.py
D:/VScodeWorkspace/python\practice_file_code11-06.py
D:/VScodeWorkspace/python\practice_file_data_check.py
D:/VScodeWorkspace/python\practice_file_data_check_test.py
D:/VScodeWorkspace/python\text.txt
D:/VScodeWorkspace/python\연습\연습_data1 - 복사본.txt
D:/VScodeWorkspace/python\연습\연습_data1.txt
D:/VScodeWorkspace/python\연습\1.DS_Store\연습_data1 - 복사본 (2).txt

 

폴더

 

 

file for file in folder_list if '.py' in file

 

import os
folder_dir = 'D:/VScodeWorkspace/python'
folder_list = os.listdir(folder_dir)
folder_list = [file for file in folder_list if '.py' in file]
print(folder_list)
fruits=['사과','딸기','배']
fruit =  [fruit for fruit in fruits if '사' in fruit]
print(fruit)

위의 문장은 아래 문장을 한줄로 줄인 것.

 

차이점은 

위 문장은 list 타입

아래 문장은 str타입

fruits=['사과','딸기','배']
for fruit in fruits:
  if '사' in fruit:
    print(fruit)

출력

['practice_file_code11-01.py', 'practice_file_code11-04.py',
'practice_file_code11-06.py', 'practice_file_data_check.py',
'practice_file_data_check_test.py']
['사과']

 

사과

 

 

Python으로 JSON 데이터 읽고 쓰기

(1) Python 객체를 JSON 데이터로 쓰기, 직렬화, 인코딩 (Write Python object to JSON, Serialization, Encoding)

(2) JSON 포맷 데이터를 Python 객체로 읽기, 역직렬화, 디코딩 (Read JSON to Python, Deserialization, Decoding)

하는 방법을 소개하겠습니다. 

 

위의 Python - JSON 간 변환 표(conversion table b/w python and JSON)에서 보는 바와 같이, python의 list, tuple 이 JSON의 array로 변환되며, JSON의 array는 pythonhon의 list로 변환됩니다. 따라서 Python의 tuple을 JSON으로 변환하면 JSON array가 되며, 이를 다시 Python으로 재변환하면 이땐 python의 tuple이 아니라 list로 변환된다는 점은 인식하고 사용하기 바랍니다. 

 

(1) Python 객체를 JSON 데이터로 쓰기, 직렬화, 인코딩: json.dumps()
      (Write Python object to JSON, Serialization, Encoding)

python 객체를 JSON 데이터로 만들어서 쓰기 위해서는 파이썬의 내장 json 모듈이 필요합니다. 

 import json

 

아래와 같은 홍길동 이라는 학생의 정보를 담고 있는 사전형 자료(dictionary)를 json.dump()와 json.dumps() 의 두가지 방법으로 JSON 포맷 데이터로 만들어보겠습니다. 

student_data = {
    "1.FirstName": "Gildong",
    "2.LastName": "Hong",
    "3.Age": 20, 
    "4.University": "Yonsei University",
    "5.Courses": [
        {
            "Major": "Statistics", 
            "Classes": ["Probability", 
                        "Generalized Linear Model", 
                        "Categorical Data Analysis"]
        }, 
        {
            "Minor": "ComputerScience", 
            "Classes": ["Data Structure", 
                        "Programming", 
                        "Algorithms"]
        }
    ]
} 

 

(2-1) with open(): json.dump() 를 사용해서 JSON 포맷 데이터를 디스크에 쓰기

with open("student_file.json", "w") 로 "student_file.json" 이름의 파일을 쓰기("w") 모드로 열어놓고, json.dump(student_data, json_file) 로 직렬화해서 JSON으로 내보내고자 하는 객체 student_data를, 직렬화된 데이터가 쓰여질 파일 json_file 에 쓰기를 해주었습니다. 

import json
with open("student_file.json", "w") as json_file:
    json.dump(student_data, json_file)

 

그러면 아래의 화면캡쳐에서 보는 바와 같이 'student_file.json'이라는 이름의 JSON 포맷 데이터가 새로 생성되었음을 알 수 있습니다.

 

 

(2-2) json.dumps()를 사용해서 JSON 포맷 데이터를 메모리에 만들기

만약 메모리 상에 JSON 포맷 데이터를 만들어놓고 python에서 계속 작업을 하려면 json.dumps() 를 사용합니다.

import json
st_json = json.dumps(student_data)
print(st_json)

 

이때 만약 json.dumps()가 아니라 json.dump() 처럼 's'를 빼먹으면 TypeError가 발생하므로 주의하세요. 

# use json.dumps() instead of json.dump()
st_json = json.dump(student_data)

 

json.dumps()로 파이썬 객체를 직렬화해서 JSON으로 쓸 때 사람이 보기에 좀더 쉽도록 'indent = int' 로 들여쓰기(indentation) 옵션을 설정할 수 있습니다. 아래 예시는 indent=4 로 설정한건데요, 한결 보기에 가독성이 좋아졌습니다. 



import json
st_json2 = json.dumps(student_data, indent=4)
print(st_json2)
{

 

'sort_keys=True' 를 설정해주면 키(keys)를 기준으로 정렬해서 직렬화하여 내보낼 수도 있습니다. 

import json
st_json3 = json.dumps(student_data, indent=4, sort_keys=True)
print(st_json3)

 

 

 

 (2) JSON 포맷 데이터를 Python 객체로 읽기, 역직렬화, 디코딩: json.loads()
      (Read JSON to Python, Deserialization, Decoding)

 

(2-1) 디스크에 있는 JSON 포맷 데이터를 json.load()를 사용하여 Python 객체로 읽어오기 (역직렬화, 디코딩 하기)

이어서, (1)번에서 with open(): json.dump() 로 만들어놓은 JSON 포맷의 데이터 "student_file.json" 를 Python 으로 역질렬화(deserialization)해서 읽어와 보겠습니다. with open("student_file.json", "r") 로 읽기 모드("r")로 JSON파일을 열어 후에, json.load(st_json)으로 디코딩하였습니다. 

import json
with open("student_file.json", "r") as st_json:
    st_python = json.load(st_json)


st_python

 

이때 json.loads() 처럼 's'를 붙이면 TypeError: the JSON object must be str, not 'TextIOWrapper'가 발생합니다. (json.loads()가 아니라 json.load() 를 사용해야 함)

# use json.load() instead of json.loads()
with open("student_json_file.json", "r") as st_json:
    st_python = json.loads(st_json)
 

 

 

(2-2) 메모리에 있는 JSON 포맷 데이터를 json.loads()로 Python 객체로 읽기 (역직렬화, 디코딩하기)

import json
st_python2 = json.loads(st_json3)
st_python2

 

이때 만약 json.loads() 대신에 's'를 빼고 json.load()를 사용하면 AttributeError: 'str' object has no attribute 'read' 가 발생하니 주의하기 바랍니다. 

# use json.loads() instead of json.load()
st_python2 = json.load(st_json3)
---------------------------------------------------------------------------

 

많은 도움이 되었기를 바랍니다. 

다음번 포스팅에서는 '웹(API)으로 부터 JSON 포맷 자료를 Python으로 읽어와서 pandas DataFrame으로 만드는 방법(https://rfriend.tistory.com/475)을 소개하겠습니다. 

Python으로 XML 파일 읽기, 쓰기는 https://rfriend.tistory.com/477 를 참고하세요. 

Python으로 YAML 파일 읽기, 쓰기는 https://rfriend.tistory.com/540 를 참고하세요. 



출처: https://rfriend.tistory.com/474 [R, Python 분석과 프로그래밍의 친구 (by R Friend)]

 

 

Python json 가져오기, 정보 추출 방법

안녕하세요. 이번 글에서는 파이썬에서 json 파일을 읽고

정보를 파싱하는 방법에 대해서 간략하게 살펴보도록 하겠습니다.

또한, json의 load와 loads 함수의 차이에 대해서도 같이 다루어보겠습니다.

 

우선, 예시를 위하여 아래와 같은 간단한 json 파일이 group.json 이름으로 저장되어 있다고

가정해보도록 하겠습니다.

{
	"team_name": "jimmy-ai",
	"topic": "machine learning",
	"start_date": "2022-02-23",
	"member_list":
		{
			"group_a":
				[
					{ "id": "101", "name": "aaa" },
					{ "id": "102", "name": "bbb" },
					{ "id": "103", "name": "ccc" },
					{ "id": "104", "name": "ddd" }
				]
			,
			"group_b":
				[
					{ "id": "201", "name": "eee" },
					{ "id": "202", "name": "fff" },
					{ "id": "203", "name": "ggg" },
					{ "id": "204", "name": "hhh" }
				]
		}
}

 

 

json 파일 읽기 : load 함수

파이썬에서 json 파일을 읽는 방법은 json 모듈을 import한 뒤,

load 함수를 이용하면 딕셔너리 형태로 자료를 가져올 수 있습니다.

 

디렉토리와 파일 이름에 주의하시며, 아래의 코드로 json을 파이썬에서 불러올 수 있습니다.

import json

with open ("group.json", "r") as f:
    data = json.load(f)

위의 data 변수에 딕셔너리 형태로 json 내 정보들이 저장되어 있는 것을 확인할 수 있습니다.

 

만일, 인코딩 오류가 난다면, open 내에서 encoding 인자를 'utf-8', 'cp949', 'euc-kr'으로

지정해보신 뒤 시도해주시면 됩니다.

 

 

json 내 정보 파싱 예제

위에서 불러온 json 기반 딕셔너리에서 정보를 추출하는 방법은

기본적인 딕셔너리, 리스트의 인덱싱 방법을 생각해주시면 됩니다.

 

예를 들어, 위의 group.json 파일에서 id가 203인 객체의 name을 가져와보겠습니다.

 

내부 자료가 현재 딕셔너리인지 리스트인지를 따져 한 단계씩 안쪽으로

인덱싱을 진행해보겠습니다.

 

가장 바깥쪽 자료는 딕셔너리이므로, id가 포함된 가장 바깥 key인

member_list를 기준으로 value를 가져오도록 하겠습니다.

data['member_list']

###
{'group_a': [{'id': '101', 'name': 'aaa'},
  {'id': '102', 'name': 'bbb'},
  {'id': '103', 'name': 'ccc'},
  {'id': '104', 'name': 'ddd'}],
 'group_b': [{'id': '201', 'name': 'eee'},
  {'id': '202', 'name': 'fff'},
  {'id': '203', 'name': 'ggg'},
  {'id': '204', 'name': 'hhh'}]}
 

안쪽 자료도 여전히 딕셔너리인 것을 확인하고,

id = 203인 객체를 포함하는 그룹인 group_b key를 기준으로 파싱하겠습니다.

data['member_list']['group_b']

###
[{'id': '201', 'name': 'eee'},
 {'id': '202', 'name': 'fff'},
 {'id': '203', 'name': 'ggg'},
 {'id': '204', 'name': 'hhh'}]

현재 자료는 리스트 형으로, 이 중 3번째 인자가 id = 203을 포함하고 있기에

2번 인덱스를 기준으로 인덱싱을 진행하겠습니다.

data['member_list']['group_b'][2]
# {'id': '203', 'name': 'ggg'}

이제, 최종 딕셔너리에서 key를 name으로 지정하여 값을 가져오면 완료됩니다.

data['member_list']['group_b'][2]['name']
# ggg

 

load와 loads 함수의 차이 : 파일 vs 문자열

마지막으로, 혼동하기 쉬운 json의 load와 loads 함수의 용도를 비교해보겠습니다.

 

load와 loads의 차이는 load는 json 파일을 읽어들이는 반면,

loads는 json 형태의 문자열을 읽어들이는 함수입니다.

 

예를 들어, 아래처럼 json 파일이 아니라 문자열에서 정보를 가져오는 경우에는

load가 아닌 loads 함수를 사용해야 합니다.

json_str = '''
{
	"team_name": "jimmy-ai",
	"topic": "machine learning",
	"start_date": "2022-02-23",
	"member_list":
		{
			"group_a":
				[
					{ "id": "101", "name": "aaa" },
					{ "id": "102", "name": "bbb" },
					{ "id": "103", "name": "ccc" },
					{ "id": "104", "name": "ddd" }
				]
			,
			"group_b":
				[
					{ "id": "201", "name": "eee" },
					{ "id": "202", "name": "fff" },
					{ "id": "203", "name": "ggg" },
					{ "id": "204", "name": "hhh" }
				]
		}
}'''

# load가 아닌 loads 함수를 사용
data = json.loads(json_str)

 

 

 

https://jimmy-ai.tistory.com/147

 

파이썬 json 파일 읽고 파싱하기, load와 loads 함수 비교

Python json 가져오기, 정보 추출 방법 안녕하세요. 이번 글에서는 파이썬에서 json 파일을 읽고 정보를 파싱하는 방법에 대해서 간략하게 살펴보도록 하겠습니다. 또한, json의 load와 loads 함수의 차

jimmy-ai.tistory.com

 

 

 

파이썬 함수 공부

zip과 딕셔너리

두 개의 리스트를 묶기

zip은 두 개의 리스트를 서로 묶어줄 때 사용합니다.

name = ['merona', 'gugucon']
price = [500, 1000]

z = zip(name, price)
print(list(z))

name 리스트에 아이스크림 이름이 price 리스트에 아이스크림의 가격이 순서대로 있을 때 두 리스트의 0번을 묶어주고, 1번을 묶어주는 겁니다. zip의 결과는 zip 타입의 객체이므로 우리가 알고 있는 리스트 타입으로 변환해서 값을 확인해볼 수 있습니다.

[('merona', 500), ('gugucon', 1000)]

zip을 사용하면 다음과 같이 두 리스트에 대해서 하나의 for 문으로 싶게 사용할 수 있습니다.

name = ['merona', 'gugucon']
price = [500, 1000]

for n, p in zip(name, price):
    print(n, p)

딕셔너리의 다양한 생성 방법

딕셔너리를 생성할 때 보통 다음과 같은 코드를 작성했습니다.

아이스크림1 = {"메로나": 500, "구구콘": 1000}

만약 키가 문자열인 경우에는 다음과 같은 방식으로 딕셔너리를 생성할 수 있습니다. 클래스를 공부했으므로 다음 코드의 의미가 dict 클래스의 객체를 생성하는 것임을 알 수 있습니다.

아이스크림2 = dict(메로나=500, 구구콘=1000)

마지막으로 키와 값을 하나의 튜플로 저장하고 여러 튜플을 리스트로 저장한 후 이를 통해 딕셔너리를 생성할 수도 있습니다.

아이스크림3 = dict([("메로나", 500), ("구구콘", 1000)])

zip과 딕셔너리

두 개의 서로 다른 리스트에서 하나를 key로 하고 다른 하나를 value로 해서 딕셔너리로 표현하면 좋을 때가 종종 있습니다. 앞서 아이스크림의 이름과 가격에서 이름이 key, 가격을 value로 하여 icecream 딕셔너리로 만들어봅시다.

name = ['merona', 'gugucon']
price = [500, 1000]

icecream = dict(zip(name, price))
print(icecream)
{'merona': 500, 'gugucon': 1000}

setdefault 메서드

딕셔너리에서 자주 사용하는 메서드에는 keys, values, items가 있습니다. 이번 절에서는 setdefault라는 메서드에 대해서 알아보겠습니다. 딕셔너리에 key를 추가하면서 초깃값을 설정할 때가 있습니다. 이 경우 setdefault 메서드를 사용하여 다음과 같이 코딩할 수 있습니다.

data = {}

ret = data.setdefault('a', 0)    # key로 'a'를 추가학 value 0을 설정함, setdefault는 현재 value 값을 리턴
print(ret, data)

ret = data.setdefault('a', 1)   # 이미 key가 있는 경우 setdefault 현재 value 값을 리턴
print(ret, data)

딕셔너리 원소 개수

다음과 같이 리스트에 데이터가 있을 때 각 데이터가 몇 번씩 있는지 횟수를 세야하는 경우가 종종 있습니다. 예를 들어, BTC는 2번, XRP는 1번, ETH는 3번이 존재합니다.

data = ["BTC", "BTC", "XRP", "ETH", "ETH", "ETH"]

다양한 방식으로 이를 풀어볼 수 있습니다. 먼저 리스트를 집합(set) 타입으로 변환하여 중복을 제거합니다. 그 다음 중복이 제거된 원소(예: BTC)에 대해서 리스트 count 메서드로 리스트 내에 해당 원소가 몇 개 들어있는지 알 수 있습니다.

for k in set(data):
    count = data.count(k)
    print(k, count)

strip()

 

Python strip() 함수는 Python 라이브러리에서 사용할 수 있는 내장 함수의 일부입니다. strip() 메서드는 원래 문자열의 시작과 끝에서 주어진 문자를 제거합니다. 기본적으로 strip() 함수는 문자열의 시작과 끝에서 공백을 제거하고 공백 없이 동일한 문자열을 반환합니다.

 

strip() 메서드의 구문

string.strip([문자])

매개변수

  • 문자: (선택 사항) 주어진 문자는 원래 문자열의 시작 또는 끝에서 제거됩니다.
  • 문자 매개변수가 제공되지 않으면 문자열의 시작과 끝에서 공백이 제거됩니다.

반환 값

Python String strip()은 다음을 반환합니다.

  • 제거할 문자가 지정되지 않은 경우 시작과 끝에서 공백이 제거된 원래 문자열입니다.
  • 문자열의 시작 또는 끝에 공백이 없는 경우 문자열을 있는 그대로 반환하고 원래 문자열과 일치시킵니다.
  • 문자 매개변수가 제공되고 문자가 일치하면 문자열의 시작 또는 끝에 있는 문자가 원래 문자열에서 제거되고 나머지 문자열이 반환됩니다.
  • 주어진 문자가 원래 문자열의 시작 또는 끝과 일치하지 않는 경우 문자열을 있는 그대로 반환합니다.

 

strip() 함수 예

예 1: 잘못된 데이터 유형에 대한 strip()

Python String strip() 함수는 문자열에서만 작동하며 목록, 튜플 등과 같은 다른 데이터 유형에 사용되는 경우 오류를 반환합니다.

list()에서 사용되는 예

mylist = ["a", "b", "c", "d"]
print(mylist.strip())

결과 : 오류

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'list' object has no attribute 'strip'

 

예 2: 문자 매개변수가 없는 strip()

str1 = "Welcome to Entity05"
after_strip = str1.strip()
print(after_strip)

str2 = "Welcome to Entity05"
after_strip1 = str2.strip()
print(after_strip1)

결과

Welcome to Entity05
Welcome to Entity05

 

예 3: strip() 문자 매개변수 전달

str1 = "****Welcome to Entity05****"
after_strip = str1.strip("*")
print(after_strip)

str2 = "Welcome to Entity05"
after_strip1 = str2.strip("05")
print(after_strip1)
str3 = "Welcome to Entity05"
after_strip3 = str3.strip("to")
print(after_strip3)

결과

Welcome to Entity05
Welcome to Entity
Welcome to Entity05

 

tqdm, python 진행률 프로세스바

파이썬으로 어떤 작업을 수행중인데, 프로그램이 내가 의도한 데로 돌아가고 있는 중인가, 진행상황이 궁금할 때가 있다. 시간이 걸리는 작업의 경우에 더 이런 상태 확인이 필요하다.

파이썬 모듈중에 tqdm이라는 것이 이 용도로 쓰이고 있다.

 

사용법

tqdm is very versatile and can be used in a number of ways. The three main ones are given below.

tqdm은 아주 변하기 쉽고 많은 방법으로 사용될 수 있다. 아래 세가지 주요 방법들이 있다.

 


 

Iterable-based

Wrap tqdm() around any iterable:

어느 이터러블이든 tqdm()로 감싼다. 리스트도 가능. 이터러블이 증가하는 것에 따라서, 진행률 증가.

from tqdm import tqdm
import time

text = ""
for char in tqdm(["a", "b", "c", "d"]):
    time.sleep(0.25)
    text = text + char
100%|██████████| 4/4 [00:01<00:00,  3.93it/s]

 

range(100)같은 것도 감싸면됨. 옵션 desc 에 진행 작업에 대한 설명을 추가 가능하다. 옵션 mininterval에 최소 업데이트 주기를 설정 가능하다.

from tqdm import tqdm
import time
for ii in tqdm(range(100), desc="tqdm example", mininterval=0.01): 
    # print(ii) 
    time.sleep(0.1)
tqdm example: 100%|██████████| 100/100 [00:10<00:00,  9.78it/s]

 

tqdm파라미터 설명

  • iterable : 반복자 객체
  • desc : 진행바 앞에 텍스트 출력
  • total : int, 전체 반복량
  • leave : bool, default로 True. (진행상태 잔상이 남음)
  • ncols : 진행바 컬럼길이. width 값으로 pixel 단위로 보임.
  • mininterval, maxinterval : 업데이트 주기. 기본은 mininterval=0.1 sec, maxinterval=10 sec
  • miniters : Minimum progress display update interval, in iterations.
  • ascii : True로 하면 '#'문자로 진행바가 표시됨.
  • initial : 진행 시작값. 기본은 0
  • bar_format : str
  • 전체 작업량을 알고 있고, 처리된 량으로 진행바를 표시할 경우에, update()로 진행량 추가

메소드

 

  • clear() : 삭제
  • refresh() : 강제 갱신

 

 

trange(i) is a special optimised instance of tqdm(range(i)):

trange(i)는 특별한 최적화 인스턴스다. tqdm(range(i))와 같은 기능이다.

for i in trange(100):
    time.sleep(0.01)
100%|██████████| 100/100 [00:01<00:00, 91.13it/s]

 

Instantiation outside of the loop allows for manual control over tqdm():

루프 밖에서 수동 tqdm 인스턴스 선언이 허용된다.

pbar = tqdm(["a", "b", "c", "d"])
for char in pbar:
    time.sleep(0.25)
    pbar.set_description("Processing %s" % char)
Processing d: 100%|██████████| 4/4 [00:01<00:00,  3.93it/s]

 


 

Manual

Manual control on tqdm() updates by using a with statement:

with구문을 사용해서 tqdm을 수동으로 컨트롤한다. update()로 수동으로 진행률을 증가 시킨다.

with tqdm(total=100) as pbar:
    for i in range(10):
        time.sleep(0.1)
        pbar.update(10) #10씩 증가
100%|██████████| 100/100 [00:01<00:00, 97.84it/s]

 

If the optional variable total (or an iterable with len()) is provided, predictive stats are displayed.

옵션 total이 제공되면, 예상되는 현재 상태가 디스플레이된다.

with is also optional (you can just assign tqdm() to a variable, but in this case don't forget to del or close() at the end: 

with적용하는 것도 옵션중 하나이다.

너가 그냥 tqdm함수만을 변수에 할당할 수도 있는데, 이렇게 쓰는 경우에는 끝에 del이나 close하는 것을 잊지마라.

pbar = tqdm(total=100)
for i in range(10):
    time.sleep(0.1)
    pbar.update(10)
pbar.close()
100%|██████████| 100/100 [00:01<00:00, 98.05it/s]

 

 


 

Module

Perhaps the most wonderful use of tqdm is in a script or on the command line.

아마 가장 엄청난 tqdm사용법은 스크립트나 커맨드라인 안에 있다.

 

Simply inserting tqdm (or python -m tqdm) between pipes will pass through all stdin to stdout while printing progress to stderr.

간단하게 tqdm(이나 python -m tqdm)을 pipe들 사이에 넣는다. stdin에서 stdout을 통과해서 지나가도록 한다.

 

 

The example below demonstrated counting the number of lines in all Python files in the current directory, with timing information included.

아래 예제는 현재 디렉토리내에 모든 python file내의 라인 숫자를 카운팅한다. 타이밍 정보를 포함한다.

$ time find . -name '*.py' -type f -exec cat \{} \; | wc -l
857365

real    0m3.458s
user    0m0.274s
sys     0m3.325s

$ time find . -name '*.py' -type f -exec cat \{} \; | tqdm | wc -l
857366it [00:03, 246471.31it/s]
857365

real    0m3.585s
user    0m0.862s
sys     0m3.358s

 

Note that the usual arguments for tqdm can also be specified.

보통 tqdm인자들은 또한 특정화될 수 있다.

$ find . -name '*.py' -type f -exec cat \{} \; |
    tqdm --unit loc --unit_scale --total 857366 >> /dev/null
100%|███████████████████████████████████| 857K/857K [00:04<00:00, 246Kloc/s]

 

Backing up a large directory?

큰 디렉토리를 백업 하시겠습니까?

$ 7z a -bd -r backup.7z docs/ | grep Compressing |
    tqdm --total $(find docs/ -type f | wc -l) --unit files >> backup.log
100%|███████████████████████████████▉| 8014/8014 [01:37<00:00, 82.29files/s]

https://skillmemory.tistory.com/entry/tqdm-%EC%82%AC%EC%9A%A9%EB%B2%95-python-%EC%A7%84%ED%96%89%EB%A5%A0-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4%EB%B0%94

 

tqdm 사용법 - python 진행률 프로세스바

파이썬으로 어떤 작업을 수행중인데, 프로그램이 내가 의도한 데로 돌아가고 있는 중인가, 진행상황이 궁금할 때가 있다. 시간이 걸리는 작업의 경우에 더 이런 상태 확인이 필요하다. 파이썬

skillmemory.tistory.com

 

Pandas 한번에 끝내기

 

 

s.unique()

s.value_counts()

s.isin([0.25,0.75])

korea_df=pd.DataFrame({})

korea_df.index

korea_df.columns

 

Index 객체

idx.size

idx.shape

idx.ndim

idx.dtype

idx1.append()

idx1.difference

idx1-idx2

idx1.intersection()

idx1 & idx2

idx1.union(idx2)

idx1 | idx2

idx1.delete(0)

idx1.drop(1)

idx1 ^ idx2

korea_df.loc[:'인천광역시',:'남자인구수']

korea_df.loc[korea_df.여자인구수 > 1000000]

korea_df.loc[(korea_df.여자인구수 > 1000000)&(korea_df.남여비율 > 100)]

midx = pd.MultiIndex.from_tuples(idx_tuples)

population = population.reindex(midx)

population[:,2010]

 

korea_mdf=population.unstack()

 

 

DataFrame

korea_mdf = pd.DataFrame({'총인구수' : population, '남자인구수' : male_tuple})

 

 

ratio = korea_mdf['남자인구수'] * 100 / korea_mdf['여자인구수']

 

 

다중 인덱스 생성

df = pd.DataFrame(np.random.rand(6,3), index=[['a', 'a', 'b', 'b', 'c', 'c'], [1, 2, 1, 2, 1, 2]], columns=['c1', 'c2', 'c3'])

 

pd.MultiIndex.from_arrays([['a', 'a', 'b', 'b', 'c', 'c'], [1, 2, 1, 2, 1, 2]])

 

pd.multiIndex.from_arrays([('a', 1), ('a', 2), ('b', 1), ('b', 1), ('b', 2), ( 'c', 1), ('c',2)])

pd.multiIndex.from_tuple([('a', 1), ('a', 2), ('b', 1), ('b', 1), ('b', 2), ( 'c', 1), ('c',2)])

pd.MultiIndex.from_product([['a', 'b', 'c'], [1,2]])

population.index.names = ['행정구역', '년도']

 

idx = pd.MultiIndex.from_product([['a', 'b', 'c'], [1,  2]], names=['name1', 'name2'])

 

 

인덱싱 및 슬라이싱

 

population['인천광역시', 2010]

 

population[population > 3000000]

 

population[['대구광역시', '대전광역시']]

 

mdf

 

mdf['c2', 1]

 

mdf.iloc[:3, :4]

=> 정수 인덱스 접근

 

mdf.loc[:, ('c2', 1)]

 

idx_slice = pd.IndexSlice

mdf.loc[idx_slice[:, 2], idx_slice[: ,2]]

 

다중 인덱스 재정렬

korea_mdf

 

korea_mdf = korea_mdf.sort_index()

인덱스가 가나다순으로 정렬됨

이제는

korea_mdf['서울특별시' : '인청광역시']기능을 써도 에러 뜨지 않는다

korea_mdf['서울특별시' : '인청광역시']

 

korea_mdf.unstack(level=0)

이후에 영상에선

korea_mdf.stack()

korea_mdf 로 정상출력함.

 

idx_flat = korea_mdf.reset_index(level=0)

 

 

idx_flat = korea_mdf.reset_index(level=(0, 1))

 

idx_flat.set_index(['행정구역', '년도'])

==>이전에 reset으로 index 없앤걸 set_index()로 복구 시킴

 

데이터 연산

s= pd.Series(np.random.randint(0, 10, 5))

df = pd.DataFrame(np.random.randint(0, 10, (3, 3)), columns=['A', 'B', 'C'])

 

np.exp(s)

np.cos(df * np.pi / 4)

 

s1 = pd.Series([1,3,5,7,9], index=[0, 1, 2, 3, 4])

s2 = pd.Series([2, 4, 6, 8, 10], index=[1, 2, 3, 4, 5])

s1 + s2

 

s1.add(s2, fill_value=0)

 

df1 = pd.DataFrame(np.random.randint(0, 20, (3,3)), columns = list('ACD'))

 

df2 = pd.DataFrame(np.random.randint(0, 20, (5,5)), columns = list('BAECD'))

 

 

df1 + df2

fvalue = df1.stack().mean()

df1.add(df2, fill_value=fvalue)

 

연산자 범용 함수

add() / 덧셈

a = np.random.randint( 1, 10, size=(3,3))

 

 

a + a[0]

df= pd.DataFrame(a, columns = list('ABC'))

 

df+df.iloc[0]

 

df.add(df.iloc[0])

sub() / subtract() / 뺄셈

a

a - a[0]

 

df

df - df.iloc[0]

df.sub(df.iloc[0])

df.subtract(df['B'], axis=0)

 

mul() / multply() / 곱셈

a

a * a[0]

df

df * df.iloc[1]

df.mul(df.iloc[1])

 

df.multiply(df.iloc[2])

truediv() / div() / divide() / floordiv() / 나누기

 

df / df.iloc[0]

df.truediv(df.iloc[0])

df.div(df.iloc[1])

 

df.divide(df.iloc[2])

 

a // a[0]

df.floordiv(df.iloc[0])

 

mod() / 나머지

 

df.mod(df.iloc[0])

 

pow() / 거듭제곱

 

df.pow(df,iloc[0])

 

 

row = df.iloc[0, ::2]

 

 

 

df - row 

 

sort / 정렬

s = pd.Series(range(5), index = [ 'A', 'D', 'B', 'C', 'E'])

 

s.sort_index()

s.sort_values()

 

df = pd.DataFrame(np.random.randint(0, 10, (4,4)), index = [2, 4, 1, 3], columns = list('BDAC'))

df.sort_index()

df.sort_index(axis=1)

axis =1 을 주면 컬럼명이 정렬되는 걸 볼 수 있다.

 

 

df.sort_values(by='A')

컬럼이 여러개니 기준을 정해줘야함.

 

 

df.sort_values(by=['A', 'C'])

컬럼 기준을 여러개 하고 싶을땐 리스트로!

 

Ranking / 순위

 

s= pd.Series([-2, 4, 7, 3, 0, 7, 5, -4, 2, 6])

s.rank()

==> -4값의 인덱스 번호는 7인데 -4값이 가장 작아 랭킹 1위 이므로 아래 인덱스 7의 값이 1이된다.

 

s.rank(method='first')

==>동일한 값이 있으면 먼저 적힌 애를 순위를 더 높여줌

s.rank(method='max')

동일한 랭킹이 있으면 둘다 랭킹 값을 낮춘채로 동일하게 한다.

 

 

eval() / 고성능 연산

nrows, ncols = 100000, 100

df1, df2, df3, df4 = (pd.DataFrame(np.random.rand(nrows, ncols)) for i  in range(4))

 

%timeit df1 + df2 + df3 + df4

 

%timeit pd.eval('df1 + df2 +df3 + df4')

 

%timeit df1 * -df2 / (-df3 * df4)

%timeit pd.eval('df1 * -df2 / (-df3 * df4)')

 

 

%timeit (df1 < df2) & (df2 <= df3) & (df3 != df4)

 

%timeit pd.eval('(df1 < df2) & (df2 <= df3) & (df3 != df4)')

 

 

df = pd.DataFrame(np.random.rand(100000,5), columns = ['A', 'B', 'C', 'D', 'E'])

 

 

df.eval('R = A + B / C - D * E', inplace = Ture)

 

col_mean = df.mean(1)

df['A'] + col_mean

 

df.eval('A' + @col_mean')

 

df[(df.A < 0.5) & (df.B < 0.5) & (df.c > 0.5)]

pd.eval('df[(df.A < 0.5) & (df.B < 0.5) & (df.c > 0.5)]')

df.query('(A<0.5) and (B < 0.5) and (C > 0.5)')

 

 

Concat() / Append() / 데이터 결합

 

s1 = pd.Series(['a', 'b'], index=[1, 2])

s2 = pd.Series(['c', 'd'], index=[3, 4])

pd.concat([s1, s2])

 

def create_df(cols, idx):

      data = {c: [str(c.lower()) + str(i) for i in idx] for c in cols}

      return pd.DataFrame(data, idx)

df1 = create_df('AB', [1, 2])

df2 = create_df('AB', [3, 4])

pd.concat([df1, df2])

df3 = create_df('AB', [0, 1])

df4 = create_df('AB', [0, 1])

pd.concat([df3, df4])

 

pd.concat([df1, df3], verify_integrity=True)

pd.concat([df1, df3], ignore_index=True)

 

pd.concat([df1, df3], keys = ['x', 'y'])

 

df5 = create_df('ABC', [1, 2])

df6 = create_df('BCD', [3, 4])

pd.concat([df5, df6])

 

 

pd.concate([df5, df6], join='inner')

 

pd.concat([df3, df4], axis =1)

 

병합과 조인

df1 = pd.DataFrame({'학생' : ['홍길동', '이순신', '임꺽정', '김유신'], '학과' :['경영학과', '교육학과', '컴퓨터학과', '통계학과']})

 

df2 = pd.DataFrame({'학생' : ['홍길동', '이순신', '임꺽정', '김유신'], '입학년도' :['2012', '2016', '2019', '2020']})

 

 

df3 = pd.merge(df1, df2)

 

df4 = pd.DataFrame({'학과' : ['경영학과', '교육학과', '컴퓨터학과', '통계학과'], '학과장': ['황희', '장영실', '안창호', '정약용']})

 

 

pd.merge(df3, df4)

 

df5 = pd.DataFrame({'학과':['경영학과', '교육학과', ' 교육학과', '컴퓨터학과', '컴퓨터학과, '통계학과'], '과목' : ['경영개론', '기초수학', '물리학', '프로그래밍', '운영체제', '확률론' ]})

 

pd.merge(df1, df5)

공통인 학과를 기준으로 merge를 하다보니 학생에 임꺽정 이름이 중복됨

 

여기까지가 2시간

728x90

'파이썬' 카테고리의 다른 글

[python][맥북] pandas 설치 시 오류  (0) 2022.05.01
파이썬 기초 문법 공부  (0) 2022.04.26
파이썬 pip install  (0) 2022.03.01
한글 매크로 단축키 설명?  (0) 2021.12.23
파이썬 tkinter 강좌  (0) 2021.12.23

댓글