[LIKELION] 221007

고관운·2022년 10월 7일

회고

😄 느낀점

  • 미니 프로젝트를 통해 실제 데이터를 사용해봤다. 대용량 데이터였기 때문에 실행 시간이 많이 걸릴 수 있다는 것을 통해 시간 복잡도를 고려해야할 것 같다.
  • 다음 주에 데이터베이스를 배우는데 기대된다.

😁 목표

  • CodeUp 100제 (1031~1040 풀기)
  • 백준 풀기
  • AWS EC2 띄우고 서버에 들어가서 Docker 설치하기
  • Docker에서 mysql 띄우기

3주차 Git, Java 실무 연습(80~88)

파일 읽기 내용 추가

FileReader

🟢 FileReader의 .read()는 리턴 타입이 int형

BufferedReader

최신코드

BufferedReader br = Files.newBufferedReader(
                Paths.get(filename), StandardCharsets.UTF_8)

Method 설계

Method 설계란

void readByChar(String filename) ➡ 이렇게 적어보는 것
(메소드 이름은 어떤 기능을 하는지 알 수 있도록 지어야 함)

Method 설계 종류

  • 논리적 설계 : 기능이 어떤 것인지 써보는 것
  • 물리적 설계 : Java로 코딩하면 어떤 모양이 될 것인지 써보는 것
  • 구현 : 설계 해놓은 것을 코딩

MDIS에서 데이터 다운로드

MDIS 사이트 ➡ 자료이용 ➡ 다운로드 서비스

🟢 미니 프로젝트에서 사용할 데이터 다운로드
인구 ➡ 국내인구이동통계 ➡ 인구관련연간자료(제공) ➡ 2021년 ➡ CSV파일로 저장

미니 프로젝트

주제

2021 서울에서 가장 많이 이사간 지역은 어디인지 알아내기

실습 코드

파일 생성, 쓰기

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.List;

public class CreateFile {
    // 파일 하나 생성
    public void createAFile(String filename) {
        File file = new File(filename);
        try {
            file.createNewFile();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    // List<String>을 지정한 파일에 write
    public void write(List<String> strs, String filename) {
        File file = new File(filename);

        try{
            BufferedWriter writer = new BufferedWriter(new FileWriter(file));
            for (String str : strs) {
                writer.write(str);
            }
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

🟢 createAFile : 파일 이름을 받아서 루트에 생성
🟢 write : String List를 받아 파일 이름에 작성


전입, 전출 변수를 갖는 클래스

public class PopulationMove {
    private int fromSido;
    private int toSido;

    // 생성자 추가
    public PopulationMove(int fromSido, int toSido) {
        this.fromSido = fromSido;
        this.toSido = toSido;
    }

    // 생성자 추가(오버로딩)
    public PopulationMove(String fromSido, String toSido) {
        this.fromSido = Integer.parseInt(fromSido);
        this.toSido = Integer.parseInt(toSido);
    }

    // getter 추가
    public int getFromSido() {
        return fromSido;
    }

    public int getToSido() {
        return toSido;
    }
}

🟢 생성자를 추가하여 전입, 전출을 입력 받았을 때 변수에 초기화
🔴 오버로딩 : String형으로 매개 변수가 들어오면, Int형으로 변환하여 초기화
🟢 getter : 직접적으로 값을 불러오지 못하게 private을 사용했으므로, 값을 불러올 수 있는 함수 따로 생성


주요 함수를 담고 있는 클래스

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class PopulationStatistics {
        public List<PopulationMove> readByLine(String filename, int from, int to) throws IOException {
        // String을 PopulationMove로 parsing하여 pml에 add합니다.
        List<PopulationMove> pml = new ArrayList<>();
        BufferedReader bufferedReader = new BufferedReader(
                new FileReader(filename)
        );
        String str;
        while((str = bufferedReader.readLine()) != null){
//            System.out.println(str);
            PopulationMove pm = parse(str, from, to);
            pml.add(pm);
        }
        bufferedReader.close();
        return pml;
    }

    public PopulationMove parse(String data, int from, int to){
        String[] dataSplit = data.split(",");

        return new PopulationMove(dataSplit[from], dataSplit[to]);  // 전입 : To, 전출 : From
    }

    public String fromToString(PopulationMove populationMove){
        return populationMove.getFromSido() + "," + populationMove.getToSido() + "\n";
    }

    public Map<String, Integer> HowManyFromSido(List<PopulationMove> newPml){
        Map<String, Integer> modeSeoulToSido = new HashMap<>();
        int cnt;
        String key;

        for (PopulationMove s : newPml) {
            int toSido = s.getToSido();
            key = s.getFromSido() + "," + toSido;
            cnt = modeSeoulToSido.containsKey(key) ? modeSeoulToSido.get(key) : 0;
            modeSeoulToSido.put(key, cnt + 1);
        }
        return modeSeoulToSido;
    }

    // 오버로딩
    public Map<String, Integer> HowManyFromSido(List<PopulationMove> newPml, int from){
        Map<String, Integer> modeSeoulToSido = new HashMap<>();
        int cnt;
        String key;

        for (PopulationMove s : newPml) {
            if (s.getFromSido() == from){
                int toSido = s.getToSido();
                key = s.getFromSido() + "," + toSido;
                cnt = modeSeoulToSido.containsKey(key) ? modeSeoulToSido.get(key) : 0;
                modeSeoulToSido.put(key, cnt + 1);
            }
        }
        return modeSeoulToSido;
    }

    // 오버로딩
    public Map<String, Integer> HowManyFromSido(List<PopulationMove> newPml, int from, int to){
        Map<String, Integer> modeSeoulToSido = new HashMap<>();
        int cnt;
        String key;

        for (PopulationMove s : newPml) {
            if (s.getFromSido() == from){
                int toSido = s.getToSido();
                if (toSido == to) {
                    key = s.getFromSido() + "," + toSido;
                    cnt = modeSeoulToSido.containsKey(key) ? modeSeoulToSido.get(key) : 0;
                    modeSeoulToSido.put(key, cnt + 1);
                }
            }
        }
        return modeSeoulToSido;
    }
    public String modeToSido(Map<String, Integer> modeSeoulToSido){
        int maxValue = 0;
        String maxKey = "";

        for (String key : modeSeoulToSido.keySet()) {
            if(modeSeoulToSido.get(key) > maxValue){
                maxValue = modeSeoulToSido.get(key);
                maxKey = key;
            }
        }

        return maxKey;
    }

    public Map<String, Integer> heatmapIdxMap() {
        Map<String, Integer> map = new HashMap<>();
        map.put("11", 0);
        map.put("26", 1);
        map.put("27", 2);
        map.put("28", 3);
        map.put("29", 4);
        map.put("30", 5);
        map.put("31", 6);
        map.put("36", 7);
        map.put("41", 8);
        map.put("42", 9);
        map.put("43", 10);
        map.put("44", 11);
        map.put("45", 12);
        map.put("46", 13);
        map.put("47", 14);
        map.put("48", 15);
        map.put("50", 16);

        return  map;
    }
}

🟢 readByLine : 파일을 읽어서 parse 메소드를 거쳐 PopulationMove List형태로 리턴
🟢 parse : 데이터를 split한 후, from, to 변수를 인덱스 값으로 받아 그에 맞는 splited 데이터를 PopulationMove 형태로 리턴
🟢 fromToString : PopulationMove의 fromSido, toSido 값을 묶어서 String 형태로 리턴
🟢 HowManyFromSido : 원하는대로 from, to값을 넣을 수 있도록 오버로딩
    🔹 리스트만 : 전체 전입, 전출 경우의 수별 개수
    🔹 리스트, from : 전출에 해당하는 전체 전입 경우의 수별 개수
    🔹 리스트, from, to : 해당 전입, 전출의 개수
🟢 modeToSido : 경우의 수 중 최빈값 리턴
🟢 heatmapIdxMap : 히트맵을 그릴 수 있도록 맵핑할 수 있는 Map 리턴


메소드를 사용하는 Main클래스

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class PopulationMain {
    public static void main(String[] args) throws IOException {
        PopulationStatistics populationStatistics = new PopulationStatistics();

//        // 파일 생성
//        CreateFile createFile = new CreateFile();
//        createFile.createAFile("from_to.txt");
//
//        // 파일 쓰기(from, to만 남기기)
//        String address = "D:\\고관운 자료\\멋쟁이사자처럼\\수업 자료\\221007 실습 자료\\2021_인구관련연간자료_20221006_98568.csv";
//        List<PopulationMove> pml = populationStatistics.readByLine(address, 6, 0);  // from : 전입 인덱스, to : 전출 인덱스
//
//        List<String> strings = new ArrayList<>();
//        for(PopulationMove pm : pml) {
//            String fromTo = populationStatistics.fromToString(pm);
//            strings.add(fromTo);
//        }
//
//        createFile.write(strings, "from_to.txt");

        // 새로 만든 파일로 작업
        String newAddress = "./from_to.txt";
        List<PopulationMove> newPml = populationStatistics.readByLine(newAddress, 0, 1);  // from : 전입 인덱스, to : 전출 인덱스

        // from에서 to로 간 시도의 개수 출력, 가장 많이 간 시도 출력(전체출력)
        Map<String, Integer> fromToList = populationStatistics.HowManyFromSido(newPml);
        System.out.println(fromToList);

        String modeToSido = populationStatistics.modeToSido(fromToList);
        System.out.println(modeToSido);

//        // from에서 to로 간 시도의 개수 출력, 가장 많이 간 시도 출력(from만 입력)
//        Map<String, Integer> fromToListInputFrom = populationStatistics.HowManyFromSido(newPml, 11);
//        System.out.println(fromToListInputFrom);
//
//        // from에서 to로 간 시도의 개수 출력, 가장 많이 간 시도 출력(from, to 입력) 오버로딩 이용
//        Map<String, Integer> fromToListInputFromTo = populationStatistics.HowManyFromSido(newPml, 44, 31);
//        System.out.println(fromToListInputFromTo);

        // 결과를 파일로 저장(전체 경우의 수)
        CreateFile createFile = new CreateFile();
        String targetFilename = "each_sido_cnt.txt";
        createFile.createAFile(targetFilename);

        List<String> cntResult = new ArrayList<>();
        for (String key : fromToList.keySet()){
            String s = String.format("from:%s to value:%d\n", key, fromToList.get(key));
            cntResult.add(s);
        }
        createFile.write(cntResult, targetFilename);

        // 결과를 히트맵 형식으로
        String targetFilenameForHeatmap = "each_sido_for_heatmap.txt";
        createFile.createAFile(targetFilenameForHeatmap);
        Map<String, Integer> heatMapIdxMap = populationStatistics.heatmapIdxMap();

        List<String> cntResultForHeatmap = new ArrayList<>();
        for (String key : fromToList.keySet()){
            String[] strForHeatmap = key.split(",");
            String s = String.format("[%s, %s, %s],\n", heatMapIdxMap.get(strForHeatmap[0]), heatMapIdxMap.get(strForHeatmap[1]), fromToList.get(key));
            cntResultForHeatmap.add(s);
        }
        createFile.write(cntResultForHeatmap, targetFilenameForHeatmap);
    }
}

🟢 필요한 데이터만 추출하기 위해 from_to.txt 생성 후 파일 쓰기
🟢 전체의 경우의 수를 볼 수 있는 each_sido_cnt.txt 생성
🟢 히트맵을 그릴 수 있도록 each_sido_for_heatmap.txt 생성 후 [%s, %s, %s],\n의 형태로 저장

히트맵 결과

2021년 전입, 전출 그래프

🟢 경기도 ➡ 경기도가 가장 많음 (1,164,252)
🟢 서울 ➡ 서울이 두번째로 많음 (809,201)

그래프 작성 사이트

0개의 댓글