Javaで日別データを週別データに集計する

投稿日:

本日アサイチでデータ集計をしたかったので、久しぶりに夜通しでプログラム書いちゃいました(笑)

何用かというと、日別データを週別にまとめたかっただけ、なのですが、Excelのピボットテーブルを使おうとしたら"日"の次は"月"しかなかったので、仕方なくデータ整形をすることにしました。

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;

/**
* 日別データを週別データへ集計
* @author doctor-k
*/
public class MakeWeeklyData {
/** 集計値を格納するMap */
public static HashMap valueMap = new HashMap();
/** バッチ実行日(土曜日)の日付を格納するMap */
public static HashMap dateMap = new HashMap();

/**
* メイン
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {

System.out.println("◆処理を開始します:" + new Date().toString() + ":◆");
mainControl();
System.out.println("◆処理を終了します:" + new Date().toString() + ":◆");

}

/**
* メインコントロール部
* @throws Exception
*/
private static void mainControl() throws Exception {

BufferedReader br = null;
BufferedWriter bw = null;

try {
/* 入力用ファイル読み込み */
br = new BufferedReader(new FileReader(new File("d:\\temp\\data.csv")));
String line;
StringBuilder sb = new StringBuilder();
sb.append("◆Detail of daily.\n\n");
while((line = br.readLine()) != null) {
/* データ集計 */
sb.append(getTargetDate(line));
}
sb.append("\n\n\n");
sb.append("◆Detail of week.\n\n");
/* 出力用ファイル用の整形 */
for (String key : valueMap.keySet()) {
System.out.println(key + " " + valueMap.get(key));
sb.append(key + " " + dateMap.get(key) + " " + valueMap.get(key) + "\n");
}
/* 出力用ファイル書き込み */
bw = new BufferedWriter(new FileWriter(new File("d:\\temp\\weekly.csv")));
bw.write(sb.toString());
bw.flush();


} catch (Exception e) {
throw e;
} finally {
if (br != null) br.close();
if (bw != null) bw.close();
}
}

/**
* データ集計
* @param line 入力用ファイルから読み込んだ行データ
* @return 行データ+10年1ヶ月後の日付とその登場週を付与
*/
private static String getTargetDate(String line) {
String sYear = line.substring(0, 4);
String sMonth = line.substring(5, 7);
String sDay = line.substring(8, 10);
String sValue = line.split(",")[1];

Calendar cal = Calendar.getInstance();
/** 体裁ととのえ */
setCalender(sYear, sMonth, sDay, cal);
/** 日別データを週別データに集計 */
valueMapControl(sValue, getCalender(cal));
/** 週別データが実行されるバッチ実行日(土曜日)を集計 */
dateMapControl(cal);

return dateFormat(
cal.getTime()) + " " +
cal.get(Calendar.WEEK_OF_YEAR) + " " +
sYear + sMonth + sDay + " " +
sValue + "\n";
}

/**
* 日別データを週別データに集計
* @param sValue 日別値
* @param key valueMapへの格納キー
*/
private static void valueMapControl(String sValue, String key) {
int value = 0;
if (valueMap.get(key) != null) {
value = valueMap.get(key).intValue() + new Integer(sValue).intValue();
valueMap.put(key, value);
} else {
valueMap.put(key, new Integer(sValue).intValue());
}
}

/**
* 週別データが実行されるバッチ実行日(土曜日)を求めて格納
* @param cal 未来日付のカレンダー
*/
private static void dateMapControl(Calendar cal) {
String key = "";
key = getCalender(cal);
if (dateMap.get(key) == null) {
int days = 0;
days = 7 - cal.get(Calendar.DAY_OF_WEEK);
cal.add(Calendar.DAY_OF_MONTH, days);
dateMap.put(key, dateFormat(cal.getTime()));
}
}

/**
* 10年1ヶ月後の日付を求める
* @param sYear 対象年
* @param sMonth 対象月
* @param sDay 対象日
* @param cal カレンダーオブジェクト
*/
private static void setCalender(String sYear, String sMonth, String sDay,
Calendar cal) {
cal.set(
new Integer(sYear).intValue(),
new Integer(sMonth).intValue(),
new Integer(sDay).intValue());
cal.add(Calendar.MONTH, 121);
}

/**
* 年+第〇週を文字列連結して戻す
* @param cal カレンダーオブジェクト
* @return 文字列連結された年+第〇週(例:202517=2025年第17週)
*/
private static String getCalender(Calendar cal) {
return
Integer.valueOf(cal.get(Calendar.YEAR)).toString() +
Integer.valueOf(cal.get(Calendar.WEEK_OF_YEAR)).toString() ;
}

/**
* 日付文字列フォーマット
* @param date 日付オブジェクト
* @return 整形後日付文字列(例:20001113)
*/
private static String dateFormat(Date date) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
return sdf.format(date).toString();
}


}

コードレビューして頂くとイマイチポイントがいっぱいありますね。。。泣
ちなみにこんなデータが、

2015/02/17,134
2015/02/18,136
2015/02/19,135
2015/02/20,135
2015/02/23,135
2015/02/24,134
2015/02/25,134
2015/02/26,134
2015/02/27,133
2015/03/02,133
2015/03/03,134
2015/03/04,133
2015/03/05,132
2015/03/06,132
2015/03/09,130
2015/03/10,131
2015/03/11,129
2015/03/12,128
2015/03/13,128
2015/03/16,127
2015/03/17,128

こんな感じになります。

◆Detail of daily.

20250419 16 20150217 134
20250418 16 20150218 136
20250419 16 20150219 135
20250426 17 20150220 135
20250423 17 20150223 135
20250424 17 20150224 134
20250425 17 20150225 134
20250426 17 20150226 134
20250503 18 20150227 133
20250502 18 20150302 133
20250503 18 20150303 134
20250510 19 20150304 133
20250505 19 20150305 132
20250506 19 20150306 132
20250509 19 20150309 130
20250510 19 20150310 131
20250517 20 20150311 129
20250512 20 20150312 128
20250513 20 20150313 128
20250516 20 20150316 127
20250517 20 20150317 128

◆Detail of week.

202516 20250419 405
202517 20250426 672
202518 20250503 400
202519 20250510 658
202520 20250517 640


眠いからちょっとねようっと。