তারিখের অনুরোধ থেকে অনুপস্থিত মান পূরণ করা

নিক মিহাইলোভস্কি, গুগল অ্যানালিটিক্স এপিআই টিম - অক্টোবর 2009

এই নিবন্ধটি আলোচনা করে যে কীভাবে Google Analytics ডেটা এক্সপোর্ট API থেকে প্রত্যাবর্তিত ডেটাতে অনুপস্থিত সময়ের সিরিজ মানগুলি সনাক্ত এবং ব্যাকফিল করা যায়।


তুমি শুরু করার আগে

নিবন্ধটি অনুমান করে যে আপনি জানেন কিভাবে Google Analytics ডেটা এক্সপোর্ট API কাজ করে। নমুনা কোডটি জাভাতে রয়েছে তবে আপনি আপনার পছন্দের ভাষায় ধারণাগুলি ব্যবহার করতে পারেন। এই নিবন্ধটির কোডটি ওপেন সোর্স হিসাবে দেওয়া হয়েছে এবং প্রকল্প হোস্টিং থেকে ডাউনলোড করা যেতে পারে।

এই নিবন্ধটি পড়ার পরে, আপনি শিখবেন:

  • Google Analytics ডেটা এক্সপোর্ট API তারিখের মাত্রাগুলিকে কীভাবে ব্যবহার করে।
  • কীভাবে আপনার প্রশ্নগুলিকে গোষ্ঠী ফলাফলে গঠন করবেন এবং অনুপস্থিত তারিখগুলি সনাক্ত করবেন।
  • জাভা ব্যবহার করে অনুপস্থিত মানগুলি কীভাবে পূরণ করবেন।

ভূমিকা

সময়কাল জুড়ে ডেটা তুলনা প্রসঙ্গ প্রদান করে। উদাহরণ স্বরূপ, একটি ওয়েবসাইট $1 মিলিয়ন রাজস্ব জেনারেট করার অর্থ খুব বেশি নয়। কিন্তু একটি ওয়েবসাইটের ত্রৈমাসিক বা বছরে 10 গুণ আয় বৃদ্ধির কথা বলা সত্যিই চিত্তাকর্ষক। Google Analytics API এর সাথে, ga:date , ga:day এবং ga:month মাত্রা ব্যবহার করে সময়ের সাথে সাথে ডেটা প্লট করা সহজ।

যদি আপনার ক্যোয়ারী শুধুমাত্র একটি তারিখ মাত্রা ব্যবহার করে, যদি তারিখ পরিসরের কোনো দিন শূন্য ডেটা সংগ্রহ করে, Google Analytics API তারিখগুলি ব্যাকফিল করবে এবং মেট্রিক্সের জন্য 0 মান।

ga:তারিখ ga:সেশন
2010-03-01 101
2010-03-02 0
2010-03-03 69

তবে আপনি যদি অন্যান্য মাত্রার সাথে তারিখটি জিজ্ঞাসা করেন তবে এটি কঠিন হয়ে যায়। যদি কোনো একটি তারিখের কোনো ডেটা না থাকে, তাহলে API সেই তারিখের জন্য কোনো এন্ট্রি ফেরত দেবে না । এটি শুধুমাত্র পরবর্তী উপলভ্য তারিখে চলে যাবে যাতে ডেটা রয়েছে।

ga:কীওয়ার্ড ga:তারিখ ga:সেশন
চেয়ার 2010-03-01 55
চেয়ার 2010-03-03 48

আদর্শভাবে বিশ্লেষকরা উপরের প্রথম উদাহরণের মতো একটি নির্দিষ্ট কীওয়ার্ডের জন্য অনুপস্থিত তারিখগুলি পূরণ করতে চান

এই নিবন্ধটি ব্যবহারিকভাবে ডেটা ব্যাকফিলিং করার জন্য কিছু সেরা অভ্যাস বর্ণনা করে।

পটভূমি

আসুন প্রথমে দেখা যাক কেন এই সমস্যাটি বিদ্যমান। 2টি কারণ আছে।

  1. Google Analytics শুধুমাত্র সংগৃহীত ডেটা প্রক্রিয়া করে। যদি কেউ একটি নির্দিষ্ট দিনে একটি সাইটে না আসে, তাহলে প্রক্রিয়া করার জন্য কোনও ডেটা নেই, তাই কোনও ডেটা ফেরত দেওয়া হয় না।
  2. কোন ডেটা নেই এমন তারিখের জন্য কতগুলি অতিরিক্ত মাত্রা এবং কোন মান ব্যবহার করা উচিত তা নির্ধারণ করা খুবই কঠিন৷

তাই সেগুলিকে শাসন করার জন্য একটি প্রক্রিয়া সংজ্ঞায়িত করার চেষ্টা করার পরিবর্তে, Google Analytics API ডেভেলপারের কাছে একাধিক মাত্রা রয়েছে এমন প্রশ্নের জন্য ডেটা পূরণ করার অনুশীলন ছেড়ে দেয়। ভাগ্যবান তুমি :)

কর্মসূচী পরিদর্শন

উপরের চার্টে ডেটা ব্যাকফিল করার পদক্ষেপগুলি এখানে রয়েছে৷

  1. মাত্রাগুলি সুবিধাবাদীভাবে সাজানো হয়েছে তা নিশ্চিত করতে ক্যোয়ারীটি পরিবর্তন করুন।
  2. তারিখ পরিসীমা থেকে প্রত্যাশিত তারিখ নির্ধারণ করুন.
  3. যে কোনো অনুপস্থিত তারিখ পুনরাবৃত্তি করুন এবং ব্যাকফিল করুন।
  4. অবশিষ্ট অনুপস্থিত মান পূরণ করুন.

ক্যোয়ারী পরিবর্তন করুন

তারিখগুলি ব্যাকফিল করার জন্য, আমাদের নিশ্চিত করতে হবে যে API থেকে প্রত্যাবর্তিত ডেটা এমন একটি বিন্যাসে রয়েছে যা একটি তারিখ অনুপস্থিত থাকলে তা সনাক্ত করা সহজ করে তোলে। মার্চের প্রথম 5 দিনের জন্য ga:keyword এবং ga:date উভয়ই পুনরুদ্ধার করার জন্য এখানে একটি উদাহরণ কোয়েরি রয়েছে:

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:কীওয়ার্ড ga:তারিখ ga: প্রবেশদ্বার
চেয়ার 2010-03-04 14
চেয়ার 2010-03-01 23
টেবিল 2010-03-04 18
টেবিল 2010-03-02 24
চেয়ার 2010-03-03 13

কোন তারিখগুলি অনুপস্থিত তা সনাক্ত করা সহজ করার জন্য, আমাদের প্রথমে সমস্ত মাত্রা একত্রে গোষ্ঠীভুক্ত করতে হবে। এটি মূল ক্যোয়ারীতে ব্যবহৃত মাত্রাগুলিতে কোয়েরির সাজানোর পরামিতি সেট করে করা যেতে পারে।

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

সাজানোর পরামিতি যোগ করলে এপিআই পছন্দসই ক্রমে ফলাফল প্রদান করবে।

ga:কীওয়ার্ড ga:তারিখ ga: প্রবেশদ্বার
চেয়ার 2010-03-01 23
চেয়ার 2010-03-03 13
চেয়ার 2010-03-04 14
টেবিল 2010-03-02 24
টেবিল 2010-03-04 18

দ্বিতীয় ধাপ হল নিশ্চিত করা যে প্রতিটি মাত্রার জন্য, সমস্ত তারিখ আরোহী ক্রমে ফেরত দেওয়া হয়। যদিও Google Analytics API অনেকগুলি তারিখের মাত্রা প্রদান করে, শুধুমাত্র ga:date তারিখের সীমানা (যেমন, দিন, মাস, বছর) জুড়ে সঠিকভাবে সাজানো যেতে পারে। তাই আপনি যদি তারিখগুলি ব্যাকফিল করতে চান, তাহলে নিশ্চিত করুন যে আপনার ক্যোয়ারীটি ডাইমেনশন এবং বাছাই করা ক্যোয়ারী প্যারামিটার উভয় ক্ষেত্রেই ga:date মাত্রা ব্যবহার করছে।

একবার বাছাই করা প্রশ্নটি কার্যকর করা হলে, একই ল্যান্ডিং পৃষ্ঠাগুলি একে অপরের পাশে ফিরে আসবে এবং তারিখগুলি ক্রমানুসারে হবে। একটি একক ল্যান্ডিং পৃষ্ঠার তারিখের তালিকাকে একটি সময় সিরিজ হিসাবে বিবেচনা করা যেতে পারে এবং যেহেতু সেগুলি ক্রমানুসারে রয়েছে, তাই অনুপস্থিত তারিখগুলি সনাক্ত করা অনেক সহজ।

প্রত্যাশিত তারিখ নির্ধারণ করুন

অনুপস্থিত তারিখগুলি সনাক্ত করতে, আমাদের প্রতিটি সময় সিরিজের প্রত্যাশিত তারিখগুলির সাথে API থেকে ফিরে আসা প্রকৃত তারিখগুলির তুলনা করতে হবে। আমরা এর দ্বারা কী প্রত্যাশিত তা নির্ধারণ করতে পারি:

  1. API ক্যোয়ারী থেকে প্রত্যাশিত শুরুর তারিখ নির্ধারণ করা হচ্ছে।
  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);
    }
  }

প্রত্যাশিত দিনের সংখ্যা গণনা

তারিখ পরিসরে দিনের সংখ্যা পেতে, প্রোগ্রামটি জাভা Date অবজেক্টে শুরু এবং শেষ তারিখগুলিকে পার্স করে। তারপর উভয় তারিখের মধ্যে সময় বের করতে একটি Calendar অবজেক্ট ব্যবহার করে। গণনাকে অন্তর্ভুক্ত করার জন্য তারিখের পার্থক্যের সাথে একটি দিন যোগ করা হয়।

  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);
  }

কোন তারিখগুলি অনুপস্থিত তা বের করার জন্য এখন আমাদের কাছে সমস্ত ডেটা রয়েছে।

ফলাফলে প্রতিটি সময় সিরিজ সনাক্ত করুন

একবার ক্যোয়ারীটি কার্যকর করা হলে, প্রোগ্রামটি API প্রতিক্রিয়াতে প্রতিটি DataEntry অবজেক্টের মধ্য দিয়ে যায়। যেহেতু ক্যোয়ারীটি প্রাথমিকভাবে বাছাই করা হয়েছিল, প্রতিক্রিয়াটিতে প্রতিটি কীওয়ার্ডের জন্য একটি আংশিক সময়ের সিরিজ থাকবে। তাই আমাদের প্রতিটি সময় সিরিজের শুরু খুঁজে বের করতে হবে, তারপর প্রতিটি তারিখের মধ্য দিয়ে যেতে হবে এবং 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);
  }
}

যে কোনো অনুপস্থিত তারিখ ব্যাকফিল করুন

একটি সিরিজের প্রতিটি এন্ট্রির জন্য, প্রোগ্রামটি মেট্রিক মান (প্রবেশ) সঞ্চয় করে row নামক একটি ArrayList এ। যখন একটি নতুন সময় সিরিজ সনাক্ত করা হয়, একটি নতুন সারি তৈরি করা হয় এবং প্রত্যাশিত তারিখটি প্রত্যাশিত শুরুর তারিখে সেট করা হয়।

তারপর প্রতিটি এন্ট্রির জন্য, এন্ট্রিতে তারিখের মান প্রত্যাশিত তারিখের সমান কিনা তা প্রোগ্রামটি পরীক্ষা করে। যদি তারা সমান হয়, তাহলে এন্ট্রির মেট্রিকটি সারিতে যোগ করা হয়। অন্যথায়, প্রোগ্রামটি অনুপস্থিত তারিখগুলি সনাক্ত করেছে যা ব্যাকফিল করা দরকার৷

backfillRow পদ্ধতি ব্যাকফিলিং ডেটা পরিচালনা করে। এটি প্রত্যাশিত এবং পাওয়া তারিখের পাশাপাশি বর্তমান সারি প্যারামিটার হিসাবে গ্রহণ করে। তারপরে এটি দুটি তারিখের মধ্যে দিনের সংখ্যা নির্ধারণ করে (অ-অন্তর্ভুক্ত) এবং সারিতে 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);
      }
    }
  }

পদ্ধতিটি সম্পন্ন হলে, সারিটি ডেটা দিয়ে ব্যাকফিল করা হয়েছে এবং বর্তমান ডেটা যোগ করা যেতে পারে। প্রত্যাশিত তারিখ তারপর 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 দ্বারা ফিরে আসা টাইম সিরিজের উপর উন্নত বিশ্লেষণ করা শুরু করা আগের চেয়ে আরও সহজ।