การกรอกค่าที่หายไปจากคำขอวันที่

Nick Mihailovski ทีม Google Analytics API – ตุลาคม 2009

บทความนี้อธิบายวิธีตรวจหาและทดแทนค่าอนุกรมเวลาที่ขาดหายไปในข้อมูลที่แสดงผลจาก API การส่งออกข้อมูลของ Google Analytics


ก่อนที่คุณจะเริ่มต้น

บทความนี้จะถือว่าคุณทราบวิธีการทำงานของ API การส่งออกข้อมูลของ Google Analytics โค้ดตัวอย่างจะอยู่ใน Java แต่คุณใช้แนวคิดในภาษาที่เลือกได้ โค้ดสำหรับบทความนี้จัดเตรียมไว้ให้เป็นโอเพนซอร์สและ ดาวน์โหลดได้จากการโฮสต์โปรเจ็กต์

หลังจากอ่านบทความนี้ คุณจะได้เรียนรู้เรื่องต่อไปนี้

  • วิธีที่ API การส่งออกข้อมูลของ Google Analytics จัดการกับมิติข้อมูลวันที่
  • วิธีจัดโครงสร้างคำค้นหาเพื่อจัดกลุ่มผลลัพธ์และตรวจหาวันที่หายไป
  • วิธีกรอกค่าที่ขาดหายไปโดยใช้ Java

เกริ่นนำ

การเปรียบเทียบข้อมูลในช่วงระยะเวลาหนึ่งจะให้บริบท เช่น การระบุว่าเว็บไซต์หนึ่งสร้างรายได้ 1 ล้านเหรียญสหรัฐไม่ได้หมายความว่าจะมีรายได้เท่าใด แต่การบอกว่าเว็บไซต์มีรายได้เพิ่มขึ้น 10 เท่าเทียบกับไตรมาสก่อนหน้าแบบปีต่อปีเป็นเรื่องที่น่าประทับใจจริงๆ API ของ Google Analytics ช่วยให้คุณพล็อตข้อมูลเมื่อเวลาผ่านไปได้ง่ายๆ โดยใช้มิติข้อมูล ga:date, ga:day และ ga:month

หากคำค้นหาใช้มิติข้อมูลวันที่เท่านั้น หากมีวันใดในช่วงวันที่รวบรวมข้อมูลเป็น 0 Google Analytics API จะทดแทนข้อมูลวันที่และค่า 0 สำหรับเมตริก

ga:datega:sessions
2010-03-01101
2010-03-020
2010-03-0369

อย่างไรก็ตาม จะเป็นเรื่องยากหากคุณค้นหาวันที่ร่วมกับมิติข้อมูลอื่นๆ หากวันที่ใดวันที่หนึ่งไม่มีข้อมูล API จะไม่แสดงรายการสำหรับวันที่นั้น แต่จะข้ามไปยังวันที่ว่างถัดไปที่มีข้อมูล

ga:keywordga:datega:sessions
เก้าอี้2010-03-0155
เก้าอี้2010-03-0348

ตามหลักการแล้ว นักวิเคราะห์ควรระบุวันที่ที่ขาดหายไปสำหรับคีย์เวิร์ดหนึ่งๆ ซึ่งกรอกให้เหมือนกับตัวอย่างแรกด้านบน

บทความนี้จะอธิบายแนวทางปฏิบัติแนะนำสำหรับการทดแทนข้อมูลในทางปฏิบัติ

ที่มา

ก่อนอื่น ลองมาดูสาเหตุของปัญหานี้กัน ซึ่งมี 2 สาเหตุ

  1. Google Analytics จะประมวลผลข้อมูลที่รวบรวมไว้เท่านั้น หากไม่มีใครมาที่เว็บไซต์ในวันใดวันหนึ่ง จะไม่มีข้อมูลให้ประมวลผล จึงไม่มีข้อมูลแสดงขึ้นมา
  2. การกำหนดจำนวนมิติข้อมูลเพิ่มเติมและค่าที่ควรใช้สำหรับวันที่ไม่มีข้อมูลนั้นทำได้ยากมาก

ดังนั้นแทนที่จะพยายามกำหนดกระบวนการเพียงกระบวนการเดียวเพื่อกฎเกณฑ์ทั้งหมด แต่ Google Analytics API จะปล่อยให้นักพัฒนาซอฟต์แวร์กรอกข้อมูลสำหรับคำค้นหาที่มีมิติข้อมูลหลายรายการได้ โชคดีจัง :)

ภาพรวมของโปรแกรม

ขั้นตอนการทดแทนข้อมูลในแผนภูมิด้านบนมีดังนี้

  1. แก้ไขการค้นหาเพื่อให้ระบบจัดเรียงมิติข้อมูลตามโอกาส
  2. ระบุวันที่ที่คาดไว้จากช่วงวันที่
  3. ทำซ้ำและทดแทนข้อมูลวันที่ที่ขาดหายไป
  4. กรอกค่าที่เหลือที่ยังขาดอยู่

แก้ไขคำค้นหา

ในการทดแทนวันที่ เราต้องตรวจสอบว่าข้อมูลที่แสดงผลจาก API อยู่ในรูปแบบที่ช่วยให้ตรวจหาได้ง่ายว่าข้อมูลวันที่ขาดหายไปเมื่อใด ตัวอย่างการค้นหาที่ใช้เรียกข้อมูลทั้ง ga:keyword และ ga:date ในช่วง 5 วันแรกในเดือนมีนาคมมีดังนี้

DataQuery dataQuery = new DataQuery(new URL(BASE_URL));
dataQuery.setIds(TABLE_ID);
dataQuery.setStartDate("2010-03-01");
dataQuery.setEndDate("2010-03-05");
dataQuery.setDimensions("ga:keyword,ga:date");
dataQuery.setMetrics("ga:entrances");

เมื่อระบบส่งการค้นหาไปยัง API แล้ว ผลลัพธ์จะมีรายการออบเจ็กต์ DataEntry รายการ ออบเจ็กต์รายการแต่ละรายการแสดงแถวข้อมูล โดยมีชื่อและค่าสำหรับมิติข้อมูล/เมตริก เนื่องจากไม่ได้ใช้พารามิเตอร์การจัดเรียง ผลการค้นหาจึงแสดงในลำดับที่กําหนดเอง

ga:keywordga:datega:entrances
เก้าอี้2010-03-0414
เก้าอี้2010-03-0123
โต๊ะ2010-03-0418
โต๊ะ2010-03-0224
เก้าอี้2010-03-0313

เราต้องจัดกลุ่มมิติข้อมูลทั้งหมดไว้ด้วยกันก่อน เพื่อให้ระบุวันที่ที่หายไปได้ง่ายขึ้น ซึ่งทำได้โดยการตั้งค่าพารามิเตอร์การจัดเรียงของการค้นหาเป็นมิติข้อมูลที่ใช้ในการค้นหาเดิม

dataQuery.setSort("ga:keyword,ga:date");

การเพิ่มพารามิเตอร์การจัดเรียงจะทำให้ API แสดงผลลัพธ์ในลำดับที่ต้องการ

ga:keywordga:datega:entrances
เก้าอี้2010-03-0123
เก้าอี้2010-03-0313
เก้าอี้2010-03-0414
โต๊ะ2010-03-0224
โต๊ะ2010-03-0418

ขั้นตอนที่ 2 คือการตรวจสอบว่ามิติข้อมูลทุกรายการจะแสดงวันที่ทั้งหมดตามลําดับจากน้อยไปมาก แม้ว่า Google Analytics API จะมีมิติข้อมูลวันที่อยู่จำนวนหนึ่ง แต่คุณจัดเรียงเฉพาะ ga:date ในขอบเขตวันที่ได้อย่างแม่นยำเท่านั้น (เช่น วัน เดือน ปี) ดังนั้นหากต้องการทดแทนวันที่ ให้ตรวจสอบว่าคำค้นหาใช้มิติข้อมูล ga:date ทั้งในมิติข้อมูลและการจัดเรียงพารามิเตอร์การค้นหา

เมื่อเรียกใช้การค้นหาที่จัดเรียงแล้ว หน้า Landing Page เดียวกันทั้งหมดจะแสดงผลอยู่ติดกัน และวันที่จะอยู่ในลำดับ รายการวันที่สำหรับหน้า Landing Page หน้าเดียวอาจถือเป็นอนุกรมเวลา และเนื่องจากวันที่เหล่านั้นมีลำดับเหตุการณ์ จึงสามารถระบุวันที่ที่ขาดหายไปได้ง่ายขึ้นมาก

ระบุวันที่ที่คาดไว้

ในการตรวจหาวันที่ที่ขาดหายไป เราจำเป็นต้องเปรียบเทียบวันที่จริงที่ได้จาก API กับวันที่ที่คาดไว้ในอนุกรมเวลาทั้งหมด เราสามารถทราบได้ว่าสิ่งใดที่เราคาดหวังจากสิ่งต่อไปนี้

  1. การกำหนดวันที่เริ่มต้นที่คาดไว้จากการค้นหา API
  2. นับจำนวนวันที่คาดว่าจะได้รับในช่วงวันที่ของการค้นหา

คุณใช้ทั้ง 2 ค่าร่วมกันเพื่อกำหนดวันที่ที่คาดไว้แต่ละวันได้โดยเพิ่มวันที่เริ่มต้นเป็น 1 สำหรับแต่ละวันในช่วงวันที่

การกำหนดวันที่เริ่มต้นที่คาดไว้

เราใช้พารามิเตอร์การค้นหา start-date เป็นวันที่เริ่มต้นที่คาดไว้ของชุดหนังสือได้ เนื่องจากรูปแบบวันที่ที่แสดงผลในการตอบกลับของ API yyyyMMdd แตกต่างจากรูปแบบของพารามิเตอร์การค้นหา yyyy-MM-dd เราจึงต้องแปลงรูปแบบวันที่ก่อน จึงจะใช้งานได้

เมธอด setExpectedStartDate จะแปลงรูปแบบของวันที่

  private static SimpleDateFormat queryDateFormat = new SimpleDateFormat("yyyy-MM-dd");
  private static SimpleDateFormat resultDateFormat = new SimpleDateFormat("yyyyMMdd");

  public void setExpectedStartDate(String startDate) {
    try {
      calendar.setTime(queryDateFormat.parse(startDate));
      expectedStartDate = resultDateFormat.format(calendar.getTime());
    } catch (ParseException e) {
      handleException(e);
    }
  }

การนับจำนวนวันที่คาดว่าจะได้รับ

หากต้องการทราบจำนวนวันในช่วงวันที่ โปรแกรมจะแยกวิเคราะห์วันที่เริ่มต้นและวันที่สิ้นสุดเป็นออบเจ็กต์ Java Date จากนั้นใช้ออบเจ็กต์ Calendar เพื่อหาเวลาระหว่างวันที่ทั้ง 2 วัน ระบบจะเพิ่ม 1 วันลงในความแตกต่างของวันที่เพื่อให้นับรวมด้วย

  private static final long millisInDay = 24 * 60 * 60 * 1000;

  public void setNumberOfDays(DataQuery dataQuery) {
    long startDay = 0;
    long endDay = 0;

    try {
      calendar.setTime(queryDateFormat.parse(dataQuery.getStartDate()));
      startDay = calendar.getTimeInMillis() / millisInDay;

      calendar.setTime(queryDateFormat.parse(dataQuery.getEndDate()));
      endDay = calendar.getTimeInMillis() / millisInDay;
    } catch (ParseException e) {
      handleException(e);
    }

    numberOfDays = (int) (endDay - startDay + 1);
  }

ตอนนี้เรามีข้อมูลทั้งหมดที่จำเป็นต้องใช้เพื่อค้นหาวันที่ที่หายไป

ระบุอนุกรมเวลาแต่ละชุดในผลลัพธ์

เมื่อระบบเรียกใช้การค้นหา โปรแกรมจะผ่านออบเจ็กต์ DataEntry แต่ละรายการในการตอบสนองของ API เนื่องจากมีการจัดเรียงคำค้นหาในขั้นต้น การตอบกลับจะมีอนุกรมเวลาบางส่วนสำหรับคีย์เวิร์ดแต่ละคำ เราจึงต้องค้นหาจุดเริ่มต้นของอนุกรมเวลาแต่ละชุด จากนั้นตรวจสอบแต่ละวันที่และกรอกข้อมูลที่ขาดหายไปซึ่ง API ไม่ได้ส่งคืน

โปรแกรมนี้ใช้ตัวแปร dimensionValue และ tmpDimensionValue เพื่อตรวจหาจุดเริ่มต้นของแต่ละชุด

ต่อไปนี้เป็นโค้ดทั้งหมดที่ใช้จัดการคำตอบได้ เราจะอธิบายเกี่ยวกับการกรอกข้อมูลที่ขาดหายไปด้านล่าง

public void printBackfilledResults(DataFeed dataFeed) {
  String expectedDate = "";
  String dimensionValue = "";
  List<Integer> row = null;

  for (DataEntry entry : dataFeed.getEntries()) {
    String tmpDimValue = entry.getDimensions().get(0).getValue();

    // Detect beginning of a series.
    if (!tmpDimValue.equals(dimensionValue)) {
      if (row != null) {
        forwardFillRow(row);
        printRow(dimensionValue, row);
      }

      // Create a new row.
      row = new ArrayList<Integer>(numberOfDays);
      dimensionValue = tmpDimValue;
      expectedDate = expectedStartDate;
    }

    // Backfill row.
    String foundDate = entry.getDimension("ga:date").getValue();
    if (!foundDate.equals(expectedDate)) {
      backFillRow(expectedDate, foundDate, row);
    }

    // Handle the data.
    Metric metric = entry.getMetrics().get(0);
    row.add(new Integer(metric.getValue()));
    expectedDate = getNextDate(foundDate);
  }

  // Handle the last row.
  if (row != null) {
    forwardFillRow(row);
    printRow(dimensionValue, row);
  }
}

ทดแทนข้อมูลวันที่ที่ขาดหายไป

สำหรับแต่ละรายการในชุด โปรแกรมจะจัดเก็บค่าเมตริก (รายการเข้า) ไว้ใน ArrayList ที่เรียกว่า row เมื่อตรวจพบอนุกรมเวลาใหม่ ระบบจะสร้างแถวใหม่และตั้งค่าวันที่ที่คาดไว้เป็นวันที่เริ่มต้นที่คาดไว้

จากนั้นโปรแกรมจะตรวจสอบว่าค่าวันที่ในแต่ละรายการตรงกับวันที่ที่คาดไว้หรือไม่สำหรับแต่ละรายการ หากเท่ากัน ระบบจะเพิ่มเมตริกในรายการลงในแถว มิเช่นนั้น โปรแกรมตรวจพบวันที่ที่ขาดหายไปซึ่งจำเป็นต้องทดแทนข้อมูล

เมธอด backfillRow จะจัดการการทดแทนข้อมูล ยอมรับพารามิเตอร์วันที่ที่คาดไว้และวันที่พบ รวมถึงแถวปัจจุบัน จากนั้นจะกำหนดจำนวนวันระหว่างวันที่ 2 วันที่นั้น (ไม่รวม) และเพิ่ม 0 จำนวนมากลงในแถว

  public void backFillRow(String startDate, String endDate, List<Integer> row) {
    long d1 = 0;
    long d2 = 0;

    try {
      calendar.setTime(resultDateFormat.parse(startDate));
      d1 = calendar.getTimeInMillis() / millisInDay;

      calendar.setTime(resultDateFormat.parse(endDate));
      d2 = calendar.getTimeInMillis() / millisInDay;

    } catch (ParseException e) {
      handleException(e);
    }

    long differenceInDays = d2 - d1;
    if (differenceInDays > 0) {
      for (int i = 0; i < differenceInDays; i++) {
        row.add(0);
      }
    }
  }

เมื่อดำเนินการเสร็จแล้ว ระบบจะทดแทนแถวด้วยข้อมูลและเพิ่มข้อมูลปัจจุบันได้ ระบบจะเพิ่มวันที่ที่คาดไว้เป็น 1 วันหลังจากวันที่พบโดยใช้เมธอด getNextDate

public String getNextDate(String initialDate) {
  try {
    calendar.setTime(resultDateFormat.parse(initialDate));
    calendar.add(Calendar.DATE, 1);
    return resultDateFormat.format(calendar.getTime());

  } catch (ParseException e) {
    handleException(e);
  }
  return "";
}

กรอกค่าที่เหลืออยู่

เมื่อประมวลผลข้อมูลชุดหนังสือเป็น row แล้ว เราจะต้องตรวจสอบว่าไม่มีวันที่ที่ขาดหายไปในตอนท้ายของชุดหนังสืออีก

เมธอด forwardFillRow จะแค่คำนวณความแตกต่างระหว่างจำนวนวันในการค้นหาเดิมกับขนาดปัจจุบันของแถว แล้วบวก 0 จำนวนนั้นต่อท้ายแถว

public void forwardFillRow(List<Integer> row) {
  int remainingElements = numberOfDays - row.size();
  if (remainingElements > 0) {
    for (int i = 0; i < remainingElements; i++) {
      row.add(0);
    }
  }
}

ณ จุดนี้ โปรแกรมได้เติมค่าที่ขาดหายไปในอนุกรมเวลาแล้ว เมื่อเรามีข้อมูลทั้งหมดแล้ว โปรแกรมจะพิมพ์ค่ามิติข้อมูลและเมตริกเป็นรายการที่คั่นด้วยเครื่องหมายจุลภาค

บทสรุป

เมื่อใช้ตัวอย่างนี้ คุณสามารถทดแทนข้อมูลในวันที่ API ไม่ได้แสดงผลได้อย่างง่ายดาย ดังที่กล่าวไว้ข้างต้น โซลูชันนี้นำไปปรับใช้กับภาษาโปรแกรมใดก็ได้ นักพัฒนาซอฟต์แวร์ยังปรับและประยุกต์ใช้เทคนิคเหล่านี้เพื่อจัดการกับมิติข้อมูลและเมตริกหลายรายการได้อีกด้วย ตอนนี้คุณสามารถเริ่มวิเคราะห์ขั้นสูงเกี่ยวกับอนุกรมเวลาที่แสดงผลโดย Google Analytics API ได้ง่ายกว่าที่เคย