2020-06-18 15:21:19 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <AggregateFunctions/IAggregateFunction.h>
|
2020-11-11 14:36:14 +00:00
|
|
|
#include <AggregateFunctions/StatSample.h>
|
2020-06-18 15:21:19 +00:00
|
|
|
#include <Columns/ColumnArray.h>
|
|
|
|
#include <Columns/ColumnVector.h>
|
|
|
|
#include <Columns/ColumnTuple.h>
|
|
|
|
#include <Common/assert_cast.h>
|
|
|
|
#include <Common/FieldVisitors.h>
|
2020-11-11 14:36:14 +00:00
|
|
|
#include <Common/PODArray_fwd.h>
|
2020-09-15 09:55:57 +00:00
|
|
|
#include <common/types.h>
|
2020-06-18 15:21:19 +00:00
|
|
|
#include <DataTypes/DataTypesDecimal.h>
|
|
|
|
#include <DataTypes/DataTypeNullable.h>
|
|
|
|
#include <DataTypes/DataTypesNumber.h>
|
|
|
|
#include <DataTypes/DataTypeTuple.h>
|
|
|
|
#include <IO/ReadHelpers.h>
|
|
|
|
#include <IO/WriteHelpers.h>
|
|
|
|
#include <limits>
|
|
|
|
|
|
|
|
#include <DataTypes/DataTypeArray.h>
|
|
|
|
|
|
|
|
#include <Common/ArenaAllocator.h>
|
|
|
|
|
|
|
|
#include <type_traits>
|
|
|
|
|
2020-11-11 14:36:14 +00:00
|
|
|
#include <iostream>
|
2020-06-18 15:21:19 +00:00
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
|
|
|
template <typename X = Float64, typename Y = Float64>
|
2020-09-02 12:00:54 +00:00
|
|
|
struct AggregateFunctionRankCorrelationData final
|
2020-06-18 15:21:19 +00:00
|
|
|
{
|
|
|
|
size_t size_x = 0;
|
|
|
|
|
2020-11-11 14:36:14 +00:00
|
|
|
using AllocatorFirstSample = MixedAlignedArenaAllocator<alignof(X), 4096>;
|
|
|
|
using FirstSample = PODArray<X, 32, AllocatorFirstSample>;
|
|
|
|
|
|
|
|
using AllocatorSecondSample = MixedAlignedArenaAllocator<alignof(Y), 4096>;
|
|
|
|
using SecondSample = PODArray<Y, 32, AllocatorSecondSample>;
|
2020-06-18 15:21:19 +00:00
|
|
|
|
2020-11-11 14:36:14 +00:00
|
|
|
FirstSample first;
|
|
|
|
SecondSample second;
|
2020-06-18 15:21:19 +00:00
|
|
|
};
|
|
|
|
|
2020-08-24 19:49:55 +00:00
|
|
|
template <typename X, typename Y>
|
2020-09-02 12:00:54 +00:00
|
|
|
class AggregateFunctionRankCorrelation :
|
|
|
|
public IAggregateFunctionDataHelper<AggregateFunctionRankCorrelationData<X, Y>, AggregateFunctionRankCorrelation<X, Y>>
|
2020-06-18 15:21:19 +00:00
|
|
|
{
|
2020-09-02 12:00:54 +00:00
|
|
|
using Data = AggregateFunctionRankCorrelationData<X, Y>;
|
2020-11-11 14:36:14 +00:00
|
|
|
using FirstSample = typename Data::FirstSample;
|
|
|
|
using SecondSample = typename Data::SecondSample;
|
2020-06-18 15:21:19 +00:00
|
|
|
|
|
|
|
public:
|
2020-09-02 12:00:54 +00:00
|
|
|
explicit AggregateFunctionRankCorrelation(const DataTypes & arguments)
|
|
|
|
:IAggregateFunctionDataHelper<AggregateFunctionRankCorrelationData<X, Y>,AggregateFunctionRankCorrelation<X, Y>> ({arguments}, {})
|
|
|
|
{}
|
2020-06-18 15:21:19 +00:00
|
|
|
|
|
|
|
String getName() const override
|
|
|
|
{
|
2020-09-02 12:00:54 +00:00
|
|
|
return "rankCorr";
|
2020-06-18 15:21:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
DataTypePtr getReturnType() const override
|
|
|
|
{
|
2020-08-24 19:49:55 +00:00
|
|
|
return std::make_shared<DataTypeNumber<Float64>>();
|
2020-06-18 15:21:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void insert(Data & a, const std::pair<X, Y> & x, Arena * arena) const
|
|
|
|
{
|
|
|
|
++a.size_x;
|
2020-11-11 14:36:14 +00:00
|
|
|
a.first.push_back(x.first, arena);
|
|
|
|
a.second.push_back(x.second, arena);
|
2020-06-18 15:21:19 +00:00
|
|
|
}
|
|
|
|
|
2020-08-24 19:49:55 +00:00
|
|
|
void add(AggregateDataPtr place, const IColumn ** columns, size_t row_num, Arena * arena) const override
|
2020-06-18 15:21:19 +00:00
|
|
|
{
|
|
|
|
auto & a = this->data(place);
|
|
|
|
|
|
|
|
auto new_x = assert_cast<const ColumnVector<X> &>(*columns[0]).getData()[row_num];
|
|
|
|
auto new_y = assert_cast<const ColumnVector<Y> &>(*columns[1]).getData()[row_num];
|
|
|
|
|
|
|
|
a.size_x += 1;
|
|
|
|
|
2020-11-11 14:36:14 +00:00
|
|
|
a.first.push_back(new_x, arena);
|
|
|
|
a.second.push_back(new_y, arena);
|
2020-06-18 15:21:19 +00:00
|
|
|
}
|
|
|
|
|
2020-08-24 19:49:55 +00:00
|
|
|
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena * arena) const override
|
2020-06-18 15:21:19 +00:00
|
|
|
{
|
|
|
|
auto & a = this->data(place);
|
|
|
|
auto & b = this->data(rhs);
|
|
|
|
|
|
|
|
if (b.size_x)
|
|
|
|
for (size_t i = 0; i < b.size_x; ++i)
|
2020-11-11 14:36:14 +00:00
|
|
|
insert(a, std::make_pair(b.first[i], b.second[i]), arena);
|
2020-06-18 15:21:19 +00:00
|
|
|
}
|
|
|
|
|
2020-08-24 19:49:55 +00:00
|
|
|
void serialize(ConstAggregateDataPtr place, WriteBuffer & buf) const override
|
2020-06-18 15:21:19 +00:00
|
|
|
{
|
2020-11-11 14:36:14 +00:00
|
|
|
const auto & first = this->data(place).first;
|
|
|
|
const auto & second = this->data(place).second;
|
2020-06-18 15:21:19 +00:00
|
|
|
size_t size = this->data(place).size_x;
|
|
|
|
writeVarUInt(size, buf);
|
2020-11-11 14:36:14 +00:00
|
|
|
buf.write(reinterpret_cast<const char *>(first.data()), size * sizeof(first[0]));
|
|
|
|
buf.write(reinterpret_cast<const char *>(second.data()), size * sizeof(second[0]));
|
2020-06-18 15:21:19 +00:00
|
|
|
}
|
|
|
|
|
2020-08-24 19:49:55 +00:00
|
|
|
void deserialize(AggregateDataPtr place, ReadBuffer & buf, Arena * arena) const override
|
2020-06-18 15:21:19 +00:00
|
|
|
{
|
|
|
|
size_t size = 0;
|
|
|
|
readVarUInt(size, buf);
|
|
|
|
|
2020-11-11 14:36:14 +00:00
|
|
|
auto & first = this->data(place).first;
|
|
|
|
|
|
|
|
first.resize(size, arena);
|
|
|
|
buf.read(reinterpret_cast<char *>(first.data()), size * sizeof(first[0]));
|
2020-06-18 15:21:19 +00:00
|
|
|
|
2020-11-11 14:36:14 +00:00
|
|
|
auto & second = this->data(place).second;
|
|
|
|
|
|
|
|
second.resize(size, arena);
|
|
|
|
buf.read(reinterpret_cast<char *>(second.data()), size * sizeof(second[0]));
|
2020-06-18 15:21:19 +00:00
|
|
|
}
|
|
|
|
|
2020-11-11 14:36:14 +00:00
|
|
|
void insertResultInto(AggregateDataPtr place, IColumn & to, Arena *) const override
|
2020-06-18 15:21:19 +00:00
|
|
|
{
|
2020-11-11 14:36:14 +00:00
|
|
|
/// Because ranks are adjusted, we have to store each of them in Float type.
|
|
|
|
using RanksArray = PODArrayWithStackMemory<Float64, 32>;
|
|
|
|
|
|
|
|
const auto & first = this->data(place).first;
|
|
|
|
const auto & second = this->data(place).second;
|
2020-06-18 15:21:19 +00:00
|
|
|
size_t size = this->data(place).size_x;
|
|
|
|
|
2020-11-11 14:36:14 +00:00
|
|
|
RanksArray first_ranks;
|
|
|
|
first_ranks.resize(first.size());
|
|
|
|
computeRanks<FirstSample, RanksArray>(first, first_ranks);
|
|
|
|
|
|
|
|
RanksArray second_ranks;
|
|
|
|
second_ranks.resize(second.size());
|
|
|
|
computeRanks<SecondSample, RanksArray>(second, second_ranks);
|
2020-06-18 15:21:19 +00:00
|
|
|
|
2020-10-21 22:15:24 +00:00
|
|
|
// count d^2 sum
|
2020-08-24 19:49:55 +00:00
|
|
|
Float64 answer = static_cast<Float64>(0);
|
2020-06-18 15:21:19 +00:00
|
|
|
for (size_t j = 0; j < size; ++ j)
|
2020-11-11 14:36:14 +00:00
|
|
|
answer += (first_ranks[j] - second_ranks[j]) * (first_ranks[j] - second_ranks[j]);
|
2020-06-18 15:21:19 +00:00
|
|
|
|
2020-08-24 19:49:55 +00:00
|
|
|
answer *= 6;
|
|
|
|
answer /= size * (size * size - 1);
|
|
|
|
answer = 1 - answer;
|
2020-06-18 15:21:19 +00:00
|
|
|
|
2020-08-24 19:49:55 +00:00
|
|
|
auto & column = static_cast<ColumnVector<Float64> &>(to);
|
|
|
|
column.getData().push_back(answer);
|
2020-06-18 15:21:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
2020-06-18 17:52:35 +00:00
|
|
|
};
|