class_docstr: Defines standard deviation aggregation.
  
  Uses Welford's online method for an accumulator-style computation of the
  standard deviation. This method was chosen due to its numerical
  stability, and it being computable in a single pass.
  This may give different (but more accurate) results than NumPy, Pandas,
  and sklearn, which use a less numerically stable two-pass algorithm.
  See
  https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Welford's_online_algorithm
code: def __init__(
      self,
      on: Optional[str] = None,
      ddof: int = 1,
      ignore_nulls: bool = True,
      alias_name: Optional[str] = None,
  ):
      self._set_key_fn(on)
      if alias_name:
          self._rs_name = alias_name
      else:
          self._rs_name = f"std({str(on)})"
  
      def merge(a: List[float], b: List[float]):
          # Merges two accumulations into one.
          # See
          # https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Parallel_algorithm
          M2_a, mean_a, count_a = a
          M2_b, mean_b, count_b = b
          delta = mean_b - mean_a
          count = count_a + count_b
          # NOTE: We use this mean calculation since it's more numerically
          # stable than mean_a + delta * count_b / count, which actually
          # deviates from Pandas in the ~15th decimal place and causes our
          # exact comparison tests to fail.
          mean = (mean_a * count_a + mean_b * count_b) / count
          # Update the sum of squared differences.
          M2 = M2_a + M2_b + (delta**2) * count_a * count_b / count
          return [M2, mean, count]
  
      null_merge = _null_wrap_merge(ignore_nulls, merge)
  
      def vectorized_std(block: Block) -> AggType:
          block_acc = BlockAccessor.for_block(block)
          count = block_acc.count(on)
          if count == 0 or count is None:
              # Empty or all null.
              return None
          sum_ = block_acc.sum(on, ignore_nulls)
          if sum_ is None:
              # ignore_nulls=False and at least one null.
              return None
          mean = sum_ / count
          M2 = block_acc.sum_of_squared_diffs_from_mean(
              on, ignore_nulls, mean
          )
          return [M2, mean, count]
  
      def finalize(a: List[float]):
          # Compute the final standard deviation from the accumulated
          # sum of squared differences from current mean and the count.
          M2, mean, count = a
          if count < 2:
              return 0.0
          return math.sqrt(M2 / (count - ddof))
  
      super().__init__(
          init=_null_wrap_init(lambda k: [0, 0, 0]),
          merge=null_merge,
          accumulate_block=_null_wrap_accumulate_block(
              ignore_nulls,
              vectorized_std,
              null_merge,
          ),
          finalize=_null_wrap_finalize(finalize),
          name=(self._rs_name),
      )
  
imports: import math
  from typing import TYPE_CHECKING, Callable, List, Optional, Union
  from ray.data._internal.null_aggregate import _null_wrap_accumulate_block, _null_wrap_accumulate_row, _null_wrap_finalize, _null_wrap_init, _null_wrap_merge
  from ray.data._internal.sort import SortKey
  from ray.data.block import AggType, Block, BlockAccessor, KeyType, T, U
  from ray.util.annotations import PublicAPI
label_desc: Use image node_id 1 to create a new Std object from inherited base classes: _AggregateOnKeyBase with example: obj = Std(on, ddof, ignore_nulls, alias_name)