주제 : Java로 대용량 데이터 분석하기 프로젝트
목표 : MIDS에서 받은 인구이동 데이터로 2021 서울에서 가장 많이 이사간 지역은 어디인지 알아내기
필요한 과정
기능/메소드
도전 과제
보충 개념
1. 대용량 데이터 500MB 읽기
1.
데이터 파일 다운로드 받아 읽어오기 (MDIS)
a.
메타데이터 : 데이터를 설명하는 데이터
b.
, 로 데이터 속성을 구분한 CSV 확장자 파일을 자바의 Object로 바꾸어 메모리로 읽어와야 함
c.
한 줄씩 line 읽어오는 BufferedReader 활용
d.
파일 위치 읽기 : 파일 위에서 마우스 오른쪽 클릭 > 속성 > 일반 > 위치
기존에 쓰던 코드 void 메소드로 분리
코드_PopulationStatistics
2.
클래스 생성
코드_PopulationMove
2. 데이터 메모리에 올리기
1.
데이터 파싱
a.
CSV 파일은 데이터를 ‘,’ 로 구분하므로 ‘,’로 데이터를 분해
b.
PopulationMove 생성자 오버로딩
2.
파싱한 PopulationMove 객체를 List에 저장
코드_PopulationStatistics_2
코드_PopulationMove_2
3. 파일 생성, 쓰기, 저장
•
목적 : 데이터를 더 효율적으로 저장하고 다루기 위함
1.
파일 생성 (참고: 파일 생성 기초)
2.
파일 쓰기
코드_PopulationStatistics_3
4. 저장한 파일 로드, 파싱하기
코드_PopulationStatistics_4
5. 지역별 이사 횟수 count
•
Map 사용한 getMoveCntMap 메소드 만들기
코드_PopulationStatistics_5
최종 (히트맵에 맞게 매핑 추가)
package week3.practice.dataproject;
import java.io.*;
import java.util.*;
public class PopulationStatistics {
private String address; //초기화
//4단계. parse() 로직 refactor
public PopulationMove parse(String str) { //파일 한 줄을 매개변수로
String[] splittedLine = str.split(","); //, 기준으로 분리 후 String[]으로 반환
return new PopulationMove(splittedLine[0], splittedLine[1]); //fromsido, tosido
}
public PopulationStatistics(String address) { //address를 매개변수로 하는 생성자
this.address = address;
}
//삽으로 푸듯 크게 한 줄씩 읽기
//1-1단계. 시도1 : 한 줄 읽기 메소드. 공간 복잡도가 늘어남
//FileReader fileReader = new FileReader(filename);
//BufferedReader reader = new BufferedReader(fileReader);
/* public void readByLine(String filename) throws IOException{
BufferedReader reader = new BufferedReader(new FileReader(filename)); //객체 생성
while((str = reader.readLine()) != null) { //파일 내용 한 줄씩 출력
System.out.println(str);
}
reader.close();
}*/
//2단계. refactor : 반환형을 list<PopulationMove>로 변경
public List<PopulationMove> readFileByLine(String filename) throws IOException {
List<PopulationMove> pml = new ArrayList<>();
BufferedReader reader = new BufferedReader(new FileReader(filename));
String str = "";
while ((str = reader.readLine()) != null) {
PopulationMove populationMove = parse(str);
pml.add(populationMove); //리스트에 저장
}
reader.close();
return pml; //PopulationMove 리스트 반환
}
//3-1단계. 파일 생성 메소드 작성 > 루트 디렉토리 위치에 파일 생성
public void createAFile(String filename) {
File file = new File(filename);
try { //try-catch
file.createNewFile();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
//3-2단계. 리스트 객체의 내용을 새 파일에 입력
public void write(List<String> strs, String filename) {
File file = new File(filename);
try { //try-catch
BufferedWriter writer = new BufferedWriter(new FileWriter(filename));
for (String str : strs) {
writer.write(str);
}
writer.close();
} catch (IOException e) {
e.printStackTrace(); //예외 상황 분석 용도
//.printStackTrace()는 예외 발생 당시의 호출스택에 있던 메소드의 정보와 예외 결과 출력
}
}
//6단계. 히트맵에 맞게 매핑
public String fromToString(PopulationMove populationMove) {
return populationMove.getFromSido() + "," + populationMove.getToSido()+"\n";
}
public Set<Integer> printSidoCd(List<PopulationMove> populationMoveList) {
Set<Integer> intSet = new HashSet<>();
for (PopulationMove pm : populationMoveList) {
intSet.add(pm.getToSido());
intSet.add(pm.getFromSido());
}
System.out.println(intSet);
return intSet;
}
/*(5단계. List<Population>을 매개변수로 하는 getMoveCntMapㅁ메서드 로직
1. listpopulationmove를 순환하면서 "11:26" 형태의 key를 만든다.
2. moveCntMap에서 해당 key에 해당하는 Object가 없으면 생성하고 1이라고 체크
3. key로 꺼내서 +1
4. 리턴 moveCntMap) */
public Map<String, Integer> getMoveCntMap(List<PopulationMove> pml) {
Map<String, Integer> moveCntMap = new HashMap<>();
for(PopulationMove pm : pml) {
String key = pm.getFromSido() + "," + pm.getToSido();
if(moveCntMap.get(key) == null) {
moveCntMap.put(key, 1);
}
moveCntMap.put(key, moveCntMap.get(key)+1);
}
return moveCntMap;
}
public Map<String, Integer> heatmapIdxMap() {
Map<String, Integer> heatmap = new HashMap<>();
//각 시,도 코드를 초기화
heatmap.put("11",0);
heatmap.put("26",1);
heatmap.put("27",2);
heatmap.put("28",3);
heatmap.put("29",4);
heatmap.put("30",5);
heatmap.put("31",6);
heatmap.put("36",7);
heatmap.put("41",8);
heatmap.put("42",9);
heatmap.put("43",10);
heatmap.put("44",11);
heatmap.put("45",12);
heatmap.put("46",13);
heatmap.put("47",14);
heatmap.put("48",15);
heatmap.put("50",16);
return heatmap;
}
/*
public void readByLine2(String filename) {
//1-2단계. 시도2 : 에러를 try-catch로 처리
try (BufferedReader br = Files.newBufferedReader(Paths.get(filename), StandardCharsets.UTF_8)) {
String line, str;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
catch(IOException e){
throw new RuntimeException(e);
}
}
*/
//메인
public static void main(String[] args) throws IOException {
String address = "C:\\-\\git\\src\\week3\\day5_fri";//파일경로
PopulationStatistics ps = new PopulationStatistics(address);
//2단계. statistics.readByLine(address);를 리스트 객체에 맞게 Refactor
List<PopulationMove> pml = ps.readFileByLine(address);
//5단계. file 생성 refactor
Map <String,Integer> map = ps.getMoveCntMap(pml);
//6단계. heatmap 파일 생성
Map <String, Integer> heatMapIdxMap = ps.heatmapIdxMap();
String targetFilename = "for_heatmap.txt";
ps.createAFile(targetFilename); //파일생성
List<String> cntResult = new ArrayList<>();
for(String key : map.keySet()) {
String[] fromto = key.split(","); //매핑 후 저장
String s = String.format("[%s, %s, %d],\n", heatmapIdxMap.get(fromto[0]), heatmapIdxMap.get(fromto[1]), map.get(key));
cntResult.add(s);
//String s = "key:" + key + ", value:" + map.get(key)+ "\n";
}
ps.write(cntResult, targetFilename);
}
}
Java
복사
새로 알게 된 것