정구리의 우주정복

Python Project 02. 공적마스크 api 를 사용해서 내 주변에서 판매하는 곳과 재고를 지도로 시각화하기 (4) 3일차 (마스크 재고 출력해주기) 본문

PYTHON/PROJECT

Python Project 02. 공적마스크 api 를 사용해서 내 주변에서 판매하는 곳과 재고를 지도로 시각화하기 (4) 3일차 (마스크 재고 출력해주기)

Jungry_ 2020. 4. 22. 19:54
반응형

*정보전달용 글이 아닙니다

**공부하는거임, 모르는게 있으면 댓글 달면 알려드립니당

엄청나게 머리 터질뻔

 

마스크 재고 상태를 확인할 수 있는 json 이다 ( 왜 판매처 , 재고를 같이 하지 않는거지 ??????)

Sale

code*

string

식별 코드

stock_at*

string($YYYY/MM/DD HH:mm:ss)

입고시간

remain_stat*

string

재고 상태[100개 이상(녹색): 'plenty' / 30개 이상 100개미만(노랑색): 'some' / 2개 이상 30개 미만(빨강색): 'few' / 1개 이하(회색): 'empty' / 판매중지: 'break']

created_at*

string($YYYY/MM/DD HH:mm:ss)

데이터 생성 일자

짜잔 이런 정보들을 갖고있다 식별코드는 약국 식별코드인건가 ????

 

오 뭔가 맞는것같음 그럼

코드를 가져와서 같은 코드인 행에 정보들을 넣어주면 되지않을 까 ..!

 

 


첫번째 도전

 

내가 생각한 방법은

1. 마스크 재고정보를 csv 파일로 만든다 ! (mask.csv)

2. 원래 마스크 정보에 있던 code 를 가져온다 (o_code)

3. mask.csv 안에 있는것중 code 가 o_code 인것의 정보를 가져온다 ! (w

4. 가져온걸 새로운 list에 넣어준다 (자연스럽게 순서도 같게됨)

5. list 를 원래 있던 데이터셋에 넣어준다 

 

짜잔 해결 이였는데 대실패함 ㅋㅋㅋ

def getMaskStat():
    url = 'https://8oi9s0nnth.apigw.ntruss.com/corona19-masks/v1/sales/json?page=1'
    req = requests.get(url)
    total_page = req.json()['totalPages']
    sales = req.json()['sales']
    #print(total_page)
    
    code = []
    created_at = []
    remain_stat = []
    stock_at = []
    
    for i in range(1,total_page+1):
        url = 'https://8oi9s0nnth.apigw.ntruss.com/corona19-masks/v1/sales/json?page='+str(i)
        req = requests.get(url)
        sales = req.json()['sales']
        
        for j in sales:
            code.append(j['code'])
            created_at.append(j['created_at'])
            try:
                remain_stat.append(j['remain_stat'])
            except:
                remain_stat.append(np.nan)
            try:
                stock_at.append(j['stock_at'])
            except:
                stock_at.append(np.nan)
    df_maskStatInfo = pd.DataFrame({'code':code,'created_at':created_at,
                                    'remain_stat':remain_stat,'stock_at':stock_at})    
        
    return df_maskStatInfo

            
mask_stat_info = getMaskStat()

mask_stat_info.to_csv('mask_stat_info.csv',index=False)


def getCode(mask_stat_info,drop_mask_store_info):
    code = list(drop_mask_store_info['code'])
    created_at = []
    remain_stat = []
    stock_at = []
    
    for i in range(len(code)):
        print('work')
        code_filter = mask_stat_info[mask_stat_info['code'].str.contains(code[i])]
        print(code_filter['created_at'])
    #print(created_at)    
mask_data = pd.read_csv('mask_stat_info.csv')
getCode(mask_data,drop_mask_store_info)

대충 이렇게 해서 빈곳엔 nan을 넣은 csv 파일을 만들고

 

 

만든 csv 파일을 보면 nan 값을 넣어준건 안에가 비어있다 (nan 이 된건가)

 

그리고 getCode 함수를 만들어줬는데 

 

오류가 나는건 그러려니 하겠는데 (해결을 하면되니까)

 

값이

행번호  데이터값  

행에대한 정보

 

이렇게 출력되는걸 어떻게 해결을 해야할지 모르겠어서 오열중 물론 그냥 문자열 다루기 해서 잘라버릴수도있지만 그러고 싶지않다구 ㅜ

나는 그냥 2020/04/21 23:35:00 이렇게만 나왔으면 좋겠는데 앞뒤에 이상한게 많이 붙어서 나온다 ㅜㅜㅜ

 

코드를 조금조금씩 수정해서 해결하려고 했지만 이러다 평생 제자리일것같아서 결국 처음부터 생각해보는걸로 

 

 


두번째 도전

 

이번에는 딕셔너리를 이용해서 합쳐보려고 한다

 

키 : 값 에 대해서 

키 = code 

값 = [재고 , 입고시간 , . .. . . . ]  이런 형태로 딕셔너리를 만들어주는거임

{code : {'created_at':created_at,

             'remain_stack',:remain_stack,

            'stock_at':stoke_at},

 code : {'created_at':created_at,

             'remain_stack',:remain_stack,

            'stock_at':stoke_at}

 }

 

이런모양의 ? 딕셔너리안에 딕셔너리를 만들어주는

그 뒤는 똑같다

 

1. 마스크 재고정보를 딕셔너리로 만든다 !!

2. 원래 마스크 정보에 있던 code 를 가져온다 (o_code)

3. 딕셔너리 안에 키값이  o_code 인것의 정보를 가져온다 !

4. 가져온걸 새로운 list에 넣어준다 (자연스럽게 순서도 같게됨)

5. list 를 원래 있던 데이터셋에 넣어준다 

 

 

만드는 중에 계속 unhashable type: 'dict' 에러 나와서 대체 왜그런가 계속 확인했는데 자료 안에 이상한 고장난 값이 들어있었던거임 ..!!!

 

def getMaskStat():
    url = 'https://8oi9s0nnth.apigw.ntruss.com/corona19-masks/v1/sales/json?page=1'
    req = requests.get(url)
    total_page = req.json()['totalPages']
    
    stat={} #딕셔너리 생성
    for i in range(1,total_page+1):
        url = 'https://8oi9s0nnth.apigw.ntruss.com/corona19-masks/v1/sales/json?page='+str(i)
        req = requests.get(url)
        sales = req.json()['sales']
        for j in sales:
            try:
                stock_at = j['stock_at']
            except:
                stock_at = 'none'
            if stock_at != 'Invalid date':
                code=j['code']
                #print(code)
                created_at=j['created_at']
                #print(created_at)
                try:
                    remain_stat=j['remain_stat']
                except:
                    remain_stat='none'
                #print(remain_stat)

                #print(stock_at)
                stat[code] = {'created_at':created_at,
                              'remain_stat':remain_stat,
                              'stock_at': stock_at}

           
    
    return stat

            
mask_stat_info = getMaskStat()
print(mask_stat_info)

이렇게 해서 탄생한 딕셔너리 만들기 코드 

 

그 다음엔 이제 합쳐주는 부분인데 까먹으면 안되는게 저 두 인자의 code 의 총개수(len) 은 서로 다르기 때문에

drop_mask_store_info 를 기준으로 다뤄줘야함

 

for 문안에서 code 가 없을때도 다뤄줘야 하기 때문에 try , except 문을 써줘야함

def getCode(drop_mask_store_info,mask_stat_info):
    #stat과 store 코드의 개수가 다른거 기억하기 
    code = drop_mask_store_info['code']
    
    created_at = []
    remain_stat = []
    stock_at = []
    
    for i in range(len(code)):
        try: #코드가 있는 경우
            created_at.append(mask_stat_info[code[i]]['created_at'])
            remain_stat.append(mask_stat_info[code[i]]['remain_stat'])
            stock_at.append(mask_stat_info[code[i]]['stock_at'])
        except: #코드가 없는 경우
            created_at.append('none')
            remain_stat.append('none')
            stock_at.append('none')
            
    #이제 합쳐줘야함 (데이터[칼럼명]=들어갈거)
    drop_mask_store_info['created_at']=created_at
    drop_mask_store_info['remain_stat']=remain_stat
    drop_mask_store_info['stock_at']=stock_at
    
    
    return drop_mask_store_info

get_mask_info = getCode(drop_mask_store_info,mask_stat_info)
#get_mask_info.to_csv('mask_info.csv',index=False)

 

.loc 를 쓰라는것 같지만 미안 나는 에러가 아니라면 해결을 할 의향이 없어 

 

seoul = [37.541,126.986]
m=folium.Map(location=seoul,zoom_start=10)

#이름 , 위도, 경도를 가져와주기
get_store_info = get_mask_info.loc[:,['name','lat','lng',
                                      'created_at','remain_stat','stock_at']]
#.loc[:,['','']] 이름으로 열 가져오기
name=list(get_store_info['name'])
lat =list(get_store_info['lat'])
lng =list(get_store_info['lng'])
remain_stat = list(get_store_info['remain_stat'])
stock_at = list(get_store_info['stock_at'])
colorList ={'plenty':'green',
            'some':'yellow',
            'few':'red',
            'empty':'gray',
            'break':'black',
            'none' : 'blue'
           }
amount={'plenty':'100개이상',
            'some':'30개이상 100개 미만',
            'few':'2개이상 30개미만',
            'empty':'다 팔려버렸다',
            'break':'판매중지',
            'none' : '정보없음'}
#지도에 표시해주기 위해 MarkerCluster 을 사용해준다
#location=[위도경도],popup=이름 , icon
marker_cluster = MarkerCluster().add_to(m)
for i in range(len(name)):

    folium.Marker(
    location = [lat[i],lng[i]],
    popup= '약국이름 : '+name[i]+'입고시간 : '+stock_at[i]+'재고상태 : '+amount[remain_stat[i]],
    icon=folium.Icon(color=colorList[remain_stat[i]],icon='ok')
    ).add_to(marker_cluster)
    

    

공식 문서에

수량 상태정보를 색상으로 표시할 경우 녹색(100개 이상)/노랑색(30~99개)/빨강색(2~29개)/회색(0~1개)을 준수해주시기 바랍니다.

 

라고 써져있어서 some 에 yellow 를 넣었는데 아니 노란색은 제공을 안해준다는거 그래서 주황색으로 바꿔줬음 . . 

원래 지도 딱 켜면 옆에 안내서 ? 처럼 색에 따른 재고갯수를 알려주고싶었는데 제공을 안해준덩 ..

쨋든 이렇게 해서 

m.save('map.html')

 

써서 html 파일로 만들어줬다

결과물은 

 

? 너무 구린데  가독성 똥 쨋든 ! 짜자ㅏㄴ 완성 

반응형
Comments