Giter Club home page Giter Club logo

pre-onboarding-9th-3-8's People

Contributors

hyorimcho avatar jhoon9494 avatar tnghgks avatar

Watchers

 avatar

pre-onboarding-9th-3-8's Issues

차트, 호버 기능 구현

📊 시계열 차트 만들기

  • 주어진 JSON 데이터의 key값(시간)을 기반으로 시계열 차트를 만들어주세요
  • 하나의 차트안에 Area 형태의 그래프와 Bar 형태의 그래프가 모두 존재하는 복합 그래프로 만들어주세요
  • Area 그래프의 기준값은 value_area 값을 이용해주세요
  • Bar 그래프의 기준값은 value_bar 값을 이용해주세요
  • 차트의 Y축에 대략적인 수치를 표현해주세요

🖱 호버 기능 구현

  • 특정 데이터 구역에 마우스 호버시 id, value_area, value_bar 데이터를 툴팁 형태로 제공해주세요

필터링 기능 구현

  • 필터링 기능을 구현해주세요, 필터링은 특정 데이터를 하이라이트 하는 방식으로 구현해주세요
  • 필터링 기능은 버튼 형태로 ID값(지역이름)을 이용해주세요
  • 필터링 시 버튼에서 선택한 ID값과 동일한 ID값을 가진 데이터 구역만 하이라이트 처리를 해주세요
  • 특정 데이터 구역을 클릭 시에도 필터링 기능과 동일한 형태로 동일한 ID값을 가진 데이터 구역을 하이라이트해주세요

[#4 ] PR 내용 중 type 사용 실수가 맞는 것 같은데, 잡아내지 못하네요. 제가 뭔가 놓친 걸까요?

type 사용이 잘못 된 부분

아래 파일 내용을 함께 보면서 말씀 드리겠습니다.

  • No.1
    함수의 파라미터 타입이 IChart[]로 지정되었습니다.
    타입스크립트의 타입 추론으로 리턴 타입 또한 동일합니다.

  • No.2
    함수를 호출하면서 인자로 res.data.response를 받습니다.
    헌데 이 인자 값은 mock 데이터가 그대로 넘어오는거라 No.1과 상충됩니다. (mock데이터의 형상이 IChart와는 다릅니다.)

  • No.3, No.4
    No.1에서 말씀 드린 것 처럼 IChart[] 타입으로 리턴 된 값을 마찬가지로 타입 지정한 상태 값에 set합니다.

[#4 ]

// 함수 파일 : lib/utils/transformData.ts
...
const transformData = (res: IChart[]) => {                                 //   No.1
  for (const key in res) {
    res[key].date = key;
  }
  return Object.values(res);
};
// 함수 사용 파일 : lib/hooks/useChart.ts
...
const useChart = () => {
  const [charts, setCharts] = useState<IChart[]>([]);                     //    No.4
  const { start, end } = generateStartAndEndDate(charts);

  useEffect(() => {
    const getCharts = () => {
      getData(API_URL)
        .then((res) => transformData(res.data.response))                  //    No.2
        .then(setCharts)                                                  //    No.3
        .catch(console.error);
    };

    getCharts();
  }, []);

  return { charts, start, end };
};
// 파일 : interface/chartData.d.ts                               

export interface IData {
  id: string;
  value_area: number;
  value_bar: number;
}

export interface IChart extends IData {                                //   type 확인
  date: string;
}

그래서 저는...

// 파일 : api/chartData.ts

import apiClient from '@/api';

export const getData = (url: string) => {                //   이 부분에 리턴 타입을 mock 데이터 형상과 똑같이 준다.
  try {
    return apiClient.get(url);
  } catch (e) {
    throw new Error('데이터가 없습니다.');
  }
};

위처럼 타입을 지정 해 주고, 제한 된 타입 안에서 안전(?)하고 답답(?)하게 뒷부분도 맞춰서 과제를 진행하고 있습니다.

그런데 의문인 것은...

타입스크립트가 이것을 잡아내지 못했다는 것입니다.

물론 타입스크립트의 타입 시스템이 완벽하진 않다지만, 이 정도는 No.2 부분에서 잡혔어야 하는 거 아닌가요? 함수의 인자로 들어가는 값의 타입과, 함수의 파라미터에 입혀준 타입이 상충되니 말입니다.

한편 No.1 부분에서 파라미터의 타입으로 IChart[]를 주셨기 때문에 해당 함수의 구문이 잘 동작합니다. 그렇지 않았다면 res[key].date = ... 처럼 무언가 할당 하려는 순간 에러: res에 그런 속성(date)은 없다 와 같은 에러가 나올 것입니다.

그래서 저는 어쩌면 정훈님이 이것을 의도하고 쓰셨을 수도 있다는 생각을 했습니다. 타입스크립트에는 이런저런 백도어가 많다고 하던데, 이 경우도 그렇지 않나 싶습니다.

혹시 의도해서 쓰셨다면 관련 된 설명을 조금 해 주시면 감사하겠습니다!

제가 뭔가 잘못 짚은 것이 있다면 도움 말씀 주시기 바랍니다!

Recharts dot 렌더링 이슈 공유

문제상황

  • Area chart를 필터링 하면서 id(지역명)에 해당하는 부분을 dot으로 표시하려 했습니다.
  • 그러나, 페이지에 첫 진입 시 혹은 브라우저를 새로고침할 때 브라우저를 resize 시키지 않으면 dot이 정상적으로 보이지 않았습니다.

의도한 동작

스크린샷 2023-03-16 오전 12 51 01

버그

스크린샷 2023-03-16 오전 12 51 13

해결 방안

  • Area chart의 dot 부분이 문제였기 때문에 해당 chart의 animation 효과를 false 처리하여 해결할 수 있었습니다.
  • 이외에도 여러 방법이 있었지만 로직 이외에 별도의 코드가 작성되어야 하는 부분이어서 위의 해결방법을 적용하였습니다.

recharts github issue

EDA: 목데이터 특성 파악

EDA

목데이터 특성 파악을 중심으로

  • 차트를 만드는 목적은 데이터를 통해 인사이트를 쉽게 도출하기 위함입니다.
  • 웹 시계열 차트를 만드는 과제를 수행하기 전 데이터를 파악하고 적합한 차트를 그리기 위해 EDA를 진행했습니다.
  • 과제 데이터의 경우 메타데이터가 없으므로 기본적인 특성만을 분석하고자 합니다.
  • 이 문서는 Jupyter Notebook으로 작성 후 Markdown 파일로 변환하였습니다.
  • @greyHairChooseLife in #7 (comment) 상연님 제안에 동감하여 이슈로 따로 남깁니다.

0. Setting

import warnings
warnings.filterwarnings(action='ignore')
import json, pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
plt.rcParams['font.family'] = 'Malgun Gothic'
from statsmodels.tsa.stattools import adfuller
from statsmodels.tsa.stattools import kpss

with open("public/mock/mockdata.json", encoding='utf-8') as f:
    js = json.loads(f.read())

df = pd.DataFrame(js['response']).T
df.head()
id value_area value_bar
2023-02-01 14:32:00 성북구 46 13111
2023-02-01 14:32:05 강남구 9 19143
2023-02-01 14:32:10 노원구 79 14798
2023-02-01 14:32:15 중랑구 4 14456
2023-02-01 14:32:20 노원구 97 19116
  • 데이터는 지역을 나타내는 컬럼(범주형) + 두가지 시계열 컬럼(수치형)으로 이루어져 있습니다.
  • 시계열 데이터의 경우 추세, 계절성, 안정성 세가지 요소의 파악이 중요합니다.
  • 만약에 시계열이 안정적이지 않다면 현재의 패턴이 미래에 똑같이 재현되지 않기때문에, 그대로 예측기법 등의 적용이 힘듭니다.

1. 시각화

plt.figure(figsize=(40, 20))

plt.subplot(2, 2, 1)
plt.pie(df['id'].value_counts(), labels=df['id'].value_counts().index, autopct='%.1f%%')

plt.subplot(2, 2, 2)
plt.scatter(df['value_area'], df['value_bar'])

plt.subplot(2, 2, 3)
plt.plot(df['value_area'])
plt.xticks(rotation=90)

plt.subplot(2, 2, 4)
plt.plot(df['value_bar'])
plt.xticks(rotation=90)

plt.tight_layout()
plt.show()

image

  • 범주형 데이터 id의 경우, 성북구가 28%로 조금 더 많고 그 외는 동일하게 분포되어 있습니다.
  • value_areavalue_bar는 특별한 관계를 가지지 않습니다.
  • 시계열 데이터의 경우, 추세나 계절성이 없습니다. 그러므로 안정적으로 판단됩니다.

2. 시계열 분석

ADF 테스트와 KPSS 테스트를 모두 사용하여 시계열의 안정성에 대해 교차 확인할 것입니다.

2.1. ADF 안정성 테스트

ADF 테스트는 시계열이 안정적(Stationary)인지 여부를 확인하는데 이용되는 방법입니다.

  • Null hypothesis: 기각에 실패하면 시계열이 안정적이지 않음을 의미합니다.
  • Alternative hypothesis: 귀무 가설(null hypothesis)이 기각되고 시계열이 안정적임을 의미합니다.
def adf_test(values):
    result = adfuller(values)
    print('ADF Statistics: %f' % result[0])
    print('p-value: %f' % result[1])
    print('Critical values:')
    for key, value in result[4].items():
        print('\t%s: %.3f' % (key, value))
        
print('ADF Test: value_area')
adf_test(df['value_area'])
print('\nADF Test: value_bar')
adf_test(df['value_bar'])
ADF Test: value_area
ADF Statistics: -11.450498
p-value: 0.000000
Critical values:
	1%: -3.498
	5%: -2.891
	10%: -2.583

ADF Test: value_bar
ADF Statistics: -5.163666
p-value: 0.000010
Critical values:
	1%: -3.502
	5%: -2.893
	10%: -2.583
  • p-value < 0.05 이므로 귀무 가설을 기각 합니다. 따라서 두 개의 시계열은 안정적입니다.

2.2. KPSS 안정성 테스트

시계열이 평균 또는 선형 추세 주변에 고정되어 있는지 또는 단위 루트(unit root)로 인해 고정되지 않은지 확인합니다.

  • Null hypothesis: 시계열이 안정적입니다.
  • Alternative hypothesis: 시계열이 안정적이지 않습니다.
def kpss_test(values):    
    statistic, p_value, n_lags, critical_values = kpss(values)
    
    print(f'KPSS Statistic: {statistic}')
    print(f'p-value: {p_value}')
    print(f'num lags: {n_lags}')
    print('Critial Values:')
    for key, value in critical_values.items():
        print(f'   {key} : {value}')

print('KPSS  Test: value_area')
kpss_test(df['value_area'])
print('\nKPSS  Test: value_bar')
kpss_test(df['value_bar'])
KPSS  Test: value_area
KPSS Statistic: 0.06021346300418588
p-value: 0.1
num lags: 12
Critial Values:
   10% : 0.347
   5% : 0.463
   2.5% : 0.574
   1% : 0.739

KPSS  Test: value_bar
KPSS Statistic: 0.22758849425522884
p-value: 0.1
num lags: 12
Critial Values:
   10% : 0.347
   5% : 0.463
   2.5% : 0.574
   1% : 0.739
  • p-value > 0.05 이므로 귀무 가설을 기각 할 수 없습니다. 두 개의 시계열은 안정적임을 알 수 있습니다.
  • 앞선 시각화와 교차 확인 결과를 통해 시계열 데이터 모두 안정적이라는 결론을 내릴 수 있습니다.

2.3. 지역별 안정성 테스트

현재 데이터는 여러 지역이 섞여 있습니다. 각 지역별로 구분하여도 안정적인지 확인합니다.

def adf_test_only_p_value(values):
    result = adfuller(values)
    print('ADF p-value: %f' % result[1])
        
def kpss_test_only_p_value(values):    
    statistic, p_value, n_lags, critical_values = kpss(values)
    print(f'KPSS p-value: {p_value}')

for loc in df['id'].value_counts().index:
    df_by_loc = df[df['id'] == loc]
    print(f'\n{loc} Test:')
    adf_test_only_p_value(df_by_loc['value_area'])
    kpss_test_only_p_value(df_by_loc['value_area'])
성북구 Test:
ADF p-value: 0.007769
KPSS p-value: 0.1

강남구 Test:
ADF p-value: 0.065291
KPSS p-value: 0.1

노원구 Test:
ADF p-value: 0.000026
KPSS p-value: 0.09626532001173367

중랑구 Test:
ADF p-value: 0.000000
KPSS p-value: 0.08952778863900929
  • 강남구의 ADF 테스트 결과를 제외하고는 유의 수준 0.05에서 같은 추론을 할 수 있습니다.
  • 즉 지역별로 구분하여도 안정성을 가진다고 판단됩니다.

3. 결론

분석을 통해 파악한 특성은 아래와 같습니다.

  • 범주형 데이터 id의 경우, 성북구가 28%로 조금 더 많고 그 외는 동일하게 분포되어 있습니다.
  • value_areavalue_bar특별한 관계를 가지지 않습니다.
  • 시계열 데이터는 추세와 계절성 없이 모두 안정적이라는 추론이 가능합니다. 그러므로 추가적인 처리 없이 시계열 모델링이 가능합니다.

용어

  • [추세, Trend]: 장기적으로 증가하거나, 감소하는 경향성이 존재하는 것
  • [계절성, Seasonality]: 계절적 요인의 영향을 받아 1년, 혹은 일정 기간 안에 반복적으로 나타나는 패턴
  • [안정성, 정상성, Stationary]: 시간에 상관없이 일정한 성질을 띠고 있는 것

Reference

Charts 크기에 따른 하이라이트 이슈

문제상황

  • 브라우저의 최대 크기일 시 제일 오른쪽 항목 하이라이트 누락
  • 브라우저의 크기가 일정 수준 이하로 내려가면 정상화

문제원인

ifOverflow 'discard' | 'hidden' | 'visible' | 'extendDomain'
부분적으로 캔버스 밖에 있는 경우 참조 영역을 그리는 방법을 정의합니다. 'discard'로 설정하면 참조 영역이 전혀 그려지지 않습니다. '숨김'으로 설정하면 참조 영역이 캔버스에 잘립니다. 'visible'로 설정하면 참조 영역이 완전히 그려집니다. 'extendDomain'으로 설정하면 참조 영역이 캔버스에 맞도록 오버플로된 축의 도메인이 확장됩니다.
DEFAULT: 'discard'
https://recharts.org/en-US/api/ReferenceArea#ifOverflow

  • 크기가 최대일 때 부분적으로 캔버스 밖으로 나간 ReferenceArea가 무시됨으로 써 발생

버그

image

해결 방안

-ReferenceArea 의 ifOverflow 속성을 visible로 변경 후 정상화

import 순서를 정해서 팀 컨벤션에 추가하면 좋을 것 같습니다.

1.

PR 된 코드 받아서 약간 정리하다가 생각이 나서요. 지난주 세션이었나요? 멘토님께서 말씀하셨던 부분이기도 하고요.

저 개인적으로는 에디터 기능이 너무 좋아서 애초에 import 쪽을 쳐다 볼 일이 거의 없긴 합니다.

하지만 리뷰 할 때는 의미가 있는 것 같아요. 저희 팀원끼리는 공통 된 코드를 쓰니까 여전히 들여다 볼 일이 적지만, 처음 소스코드를 전달 받고 리뷰(평가)를 하는 입장에서는 가독성에 도움이 된다고 생각합니다.

제가 먼저 제안을 해 보자면,

import 라이브러리
import 리액트 내장 훅
import 커스텀 훅
import 컴포넌트
import 기타(유틸 함수 / 상수 /스타일 등등... )
import type

저 개인적으로 개발 순서에 따라 import 해 나가다 보면 대략 이렇게 쌓아지더라고요. 타입의 경우만 좀 쳐다볼 일이 생겨서 가장 빨리 볼 수 있는 곳에 두곤 했습니다.

2.

한 가지만 더 제안 드려보자면 커스텀 훅을 export 할 때 default export 말고 그냥 export하는 건 별로일까요? 저는 커스텀 훅을 써 보는 것이 처음인데, import { useSomething } from ...의 형태를 보면 훅이라는 걸 더 빨리 알 것 같다는 생각이 들어서요.


가타부타 또는 의견과 근거를 기대 해 봅니다!!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.