{
  "id": 4375344,
  "title": "The first thing I check before trusting any dataset",
  "url": "https://urgent.news/2026/08/30/the-first-thing-i-check-before-trusting-any-dataset",
  "topic": "tech",
  "section": "Tech",
  "published": "2026-08-30T07:42:02.000Z",
  "source": {
    "name": "Dev.to",
    "slug": "dev-to",
    "url": "https://dev.to/leomarsh886/the-first-thing-i-check-before-trusting-any-dataset-5bm3"
  },
  "original_language": "en",
  "account": "Before trusting any dataset, the first thing I check is the description provided. However, I have found that these descriptions often do not align with the actual data. This discrepancy occurs because the person writing the README typically describes the dataset as intended, or how it appeared a few months earlier. The true nature of the data has gradually changed over time, leading to subtle drifts. To ensure accuracy, I run a simple ritual before performing any computations.\n\nThe first step in this ritual is to examine the null values in the dataset. The obvious approach is to use `df.isna().sum()`, which counts the number of null values in each column. An often overlooked step is to identify values that appear null but are not encoded as null. These can include various representations such as empty strings, specific characters like `-`, `N/A`, `NA`, `null`, `None`, `0`, `-1`, or `9999`. I create a list of these suspect values and iterate through each column of type `object`. For each column, I count how many times a value appears in the list of suspects. If there are any suspicious values, I print out the column name and the count of suspicious values. This step is crucial because a column with 0% nulls but 30% dashes is essentially a 30%-null column, rendering any computed mean meaningless.\n\nNext, I focus on the distribution of the data rather than just the summary statistics. The `df.describe()` function provides basic summary statistics like the mean, median, and standard deviation. However, it does not reveal the full picture. For instance, if a continuous column has a single value appearing thousands of times, that value is typically a default, cap, or placeholder rather than an actual measurement. To uncover this, I use `df[value].value_counts().head(10)` to see the most frequent values and complement it with a histogram plot, `df[value].plot.hist(bins=50)`, to visualize the distribution. This step helps in identifying data that is dominated by a single value, indicating that the dataset might be missing crucial information.\n\nLastly, I check the time column against my assumptions to ensure its integrity. Timestamps are essential for time-series analysis, but they can be misleading if not properly validated. I ask three key questions: first, what timezone is the timestamp in? The README might state it is in UTC, but I verify this by checking if daily events cluster around midnight or a specific time that does not align with UTC. Second, I assess whether the timestamp data is complete. By grouping the data by day and counting the rows, I look for gaps or sudden drops, which often indicate an ingestion failure rather than a quiet day. Finally, I verify that the timestamp column is monotonic where it should be. For example, the `created_at` timestamp should never be later than the `updated_at` timestamp. If there are instances where this rule is violated, it raises suspicion and warrants further investigation. I print out the size of the data grouped by date and identify any days that are significantly thinner than the median, indicating potential issues.\n\nThe reason behind these checks is straightforward: these are not sophisticated techniques. The most significant errors in analysis usually stem not from selecting the wrong model but from feeding a correct model with data that does not accurately represent reality. Investing just five minutes upfront to perform these checks can save significant time and effort in correcting wrong conclusions. Therefore, my primary check when a new dataset arrives is to run this short, yet thorough, ritual. It has saved me from numerous instances of shipping incorrect conclusions.",
  "summary": "Every dataset I've ever received came with a description. Almost none of them matched the data. Not because anyone was lying. The person who wrote the README usually described the dataset as it was supposed to be, or as it was six months ago. The data itself has been quietly drifting since then. So before I compute a single mean, I run the same short ritual. It takes five minutes and has saved me…",
  "key_points": [
    "Examine null values to identify hidden nulls",
    "Analyze data distribution beyond summary statistics",
    "Validate time column integrity against assumptions"
  ],
  "editors_take": null,
  "illustration": null,
  "coverage": {
    "outlets": 1,
    "also_reported_by": []
  },
  "ai_generated": true,
  "disclaimer": "Summaries, key points and the editor’s take are written by software from other outlets’ reporting and may contain errors — always check the linked original."
}