From d9672697a70f144df322e4a10e5b59f8e1f304ed Mon Sep 17 00:00:00 2001 From: Ted Middleton Date: Thu, 21 Jul 2022 16:45:50 -0700 Subject: [PATCH] Added agg::count() Also, reformatted --- mainframe/base.cpp | 1 - mainframe/base.hpp | 1 - mainframe/expression.hpp | 1 - mainframe/frame.hpp | 1 - mainframe/frame_iterator.hpp | 69 ++++---- mainframe/grouped_frame.hpp | 306 +++++++++++++++++----------------- mainframe/missing.hpp | 2 +- mainframe/series.hpp | 1 - mainframe/series_vector.hpp | 3 +- mainframe/simd.hpp | 1 - tests/mainframe_test_main.cpp | 136 ++++++++------- 11 files changed, 265 insertions(+), 257 deletions(-) diff --git a/mainframe/base.cpp b/mainframe/base.cpp index b727712..84f3a03 100644 --- a/mainframe/base.cpp +++ b/mainframe/base.cpp @@ -1,4 +1,3 @@ - // Copyright Ted Middleton 2022. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/mainframe/base.hpp b/mainframe/base.hpp index 55ebb70..44d4989 100644 --- a/mainframe/base.hpp +++ b/mainframe/base.hpp @@ -1,4 +1,3 @@ - // Copyright Ted Middleton 2022. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/mainframe/expression.hpp b/mainframe/expression.hpp index f542137..790d572 100644 --- a/mainframe/expression.hpp +++ b/mainframe/expression.hpp @@ -1,4 +1,3 @@ - // Copyright Ted Middleton 2022. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/mainframe/frame.hpp b/mainframe/frame.hpp index 3df840b..ce147b8 100644 --- a/mainframe/frame.hpp +++ b/mainframe/frame.hpp @@ -1,4 +1,3 @@ - // Copyright Ted Middleton 2022. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/mainframe/frame_iterator.hpp b/mainframe/frame_iterator.hpp index 638d0a8..8e80b35 100644 --- a/mainframe/frame_iterator.hpp +++ b/mainframe/frame_iterator.hpp @@ -1,4 +1,3 @@ - // Copyright Ted Middleton 2022. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -829,41 +828,41 @@ using const_reverse_frame_iterator = base_frame_iterator; namespace std { - template - struct hash> - { - template - size_t - operator()(const mf::_base_frame_row& fr) const - { - using T = typename mf::detail::pack_element::type; - std::hash hasher; - mf::columnindex ci; - size_t out = hasher(fr.at( ci )); - if constexpr (Ind + 1 < sizeof...(Ts)) { - out ^= operator()(fr); - } - return out; - } - }; - - template - struct hash> - { - template - size_t - operator()(const mf::_row_proxy& fr) const - { - using T = typename mf::detail::pack_element::type; - std::hash hasher; - mf::columnindex ci; - size_t out = hasher(fr.at( ci )); - if constexpr (Ind + 1 < sizeof...(Ts)) { - out ^= operator()(fr); - } - return out; +template +struct hash> +{ + template + size_t + operator()(const mf::_base_frame_row& fr) const + { + using T = typename mf::detail::pack_element::type; + std::hash hasher; + mf::columnindex ci; + size_t out = hasher(fr.at(ci)); + if constexpr (Ind + 1 < sizeof...(Ts)) { + out ^= operator()(fr); } - }; + return out; + } +}; + +template +struct hash> +{ + template + size_t + operator()(const mf::_row_proxy& fr) const + { + using T = typename mf::detail::pack_element::type; + std::hash hasher; + mf::columnindex ci; + size_t out = hasher(fr.at(ci)); + if constexpr (Ind + 1 < sizeof...(Ts)) { + out ^= operator()(fr); + } + return out; + } +}; } // namespace std #endif // INCLUDED_mainframe_frame_iterator_h diff --git a/mainframe/grouped_frame.hpp b/mainframe/grouped_frame.hpp index 0522887..4b39524 100644 --- a/mainframe/grouped_frame.hpp +++ b/mainframe/grouped_frame.hpp @@ -1,4 +1,3 @@ - // Copyright Ted Middleton 2022. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -208,26 +207,30 @@ struct get_result_frame, index_defn, Frame> { return f.columns(columnindex{}..., columnindex{}...); } - - }; template -struct sum_op : std::integral_constant {}; +struct sum_op : std::integral_constant +{}; template -struct min_op : std::integral_constant {}; +struct min_op : std::integral_constant +{}; template -struct max_op : std::integral_constant {}; +struct max_op : std::integral_constant +{}; template -struct mean_op : std::integral_constant {}; +struct mean_op : std::integral_constant +{}; template -struct stddev_op : std::integral_constant {}; +struct stddev_op : std::integral_constant +{}; -struct count_op {}; +struct count_op +{}; template struct get_result_columns_from_args; @@ -235,27 +238,23 @@ struct get_result_columns_from_args; template typename Op, size_t Ind, typename... Ops> struct get_result_columns_from_args, Op, Ops...> { - using ind_type = typename detail::pack_element::type; - using remaining_columns = - typename get_result_columns_from_args, Ops...>::type; - using type = - typename detail::prepend, remaining_columns>::type; + using ind_type = typename detail::pack_element::type; + using remaining_columns = typename get_result_columns_from_args, Ops...>::type; + using type = typename detail::prepend, remaining_columns>::type; }; template struct get_result_columns_from_args, count_op, Ops...> { - using remaining_columns = - typename get_result_columns_from_args, Ops...>::type; - using type = - typename detail::prepend, remaining_columns>::type; + using remaining_columns = typename get_result_columns_from_args, Ops...>::type; + using type = typename detail::prepend, remaining_columns>::type; }; template typename Op, size_t Ind> struct get_result_columns_from_args, Op> { using ind_type = typename detail::pack_element::type; - using type = std::tuple>; + using type = std::tuple>; }; template @@ -264,33 +263,29 @@ struct get_result_columns_from_args, count_op> using type = std::tuple>; }; -template +template struct get_frame_from_args; -template typename Op, size_t Ind, typename...Ops> +template typename Op, size_t Ind, typename... Ops> struct get_frame_from_args, Op, Ops...> { - using ind_type = typename detail::pack_element::type; - using remaining_frame_type = - typename get_frame_from_args, Ops...>::type; - using type = - typename detail::prepend::type; + using ind_type = typename detail::pack_element::type; + using remaining_frame_type = typename get_frame_from_args, Ops...>::type; + using type = typename detail::prepend::type; }; -template +template struct get_frame_from_args, count_op, Ops...> { - using remaining_frame_type = - typename get_frame_from_args, Ops...>::type; - using type = - typename detail::prepend::type; + using remaining_frame_type = typename get_frame_from_args, Ops...>::type; + using type = typename detail::prepend::type; }; template typename Op, size_t Ind> struct get_frame_from_args, Op> { using ind_type = typename detail::pack_element::type; - using type = frame; + using type = frame; }; template @@ -305,23 +300,19 @@ struct is_colind_at_argind; template struct is_colind_at_argind> { - static const bool value = - is_colind_at_argind>::value; + static const bool value = is_colind_at_argind>::value; }; -templatetypename Op, size_t ColInd, typename... Ops> -struct is_colind_at_argind, Ops...>> : - std::false_type +template typename Op, size_t ColInd, typename... Ops> +struct is_colind_at_argind, Ops...>> : std::false_type {}; -templatetypename Op, typename... Ops> -struct is_colind_at_argind, Ops...>> : - std::true_type +template typename Op, typename... Ops> +struct is_colind_at_argind, Ops...>> : std::true_type {}; template -struct is_colind_at_argind> : - std::false_type +struct is_colind_at_argind> : std::false_type {}; template @@ -330,11 +321,9 @@ struct get_aggregate_frame; template struct get_aggregate_frame, index_defn, Ops...> { - using index_frame = - typename get_index_frame, frame>::type; - using args_frame = - typename get_frame_from_args, Ops...>::type; - using type = typename detail::join_frames::type; + using index_frame = typename get_index_frame, frame>::type; + using args_frame = typename get_frame_from_args, Ops...>::type; + using type = typename detail::join_frames::type; }; } // namespace detail @@ -343,41 +332,40 @@ namespace agg { template detail::sum_op -sum( columnindex ) +sum(columnindex) { return detail::sum_op{}; } template detail::min_op -min( columnindex ) +min(columnindex) { return detail::min_op{}; } template detail::max_op -max( columnindex ) +max(columnindex) { return detail::max_op{}; } template detail::mean_op -mean( columnindex ) +mean(columnindex) { return detail::mean_op{}; } template detail::stddev_op -stddev( columnindex ) +stddev(columnindex) { return detail::stddev_op{}; } -detail::count_op -inline count() +detail::count_op inline count() { return detail::count_op{}; } @@ -415,8 +403,7 @@ class grouped_frame, Ts...> using map_type = std::unordered_map; template - using get_aggregate_frame = - detail::get_aggregate_frame, group_index_defn, Ops...>; + using get_aggregate_frame = detail::get_aggregate_frame, group_index_defn, Ops...>; public: grouped_frame(frame f) @@ -429,159 +416,167 @@ class grouped_frame, Ts...> { build_index(); - typename detail::get_result_columns_from_args, Ops...>::type - result_columns; - aggregate_rename_result_columns<0, Ops...>( result_columns ); - auto ifr = get_index_frame::op( m_frame ); + typename detail::get_result_columns_from_args, Ops...>::type result_columns; + rename_result_columns_args<0, Ops...>(result_columns); + auto ifr = get_index_frame::op(m_frame); ifr.clear(); // this is mostly to get the column names - for ( const auto& [key, rowinds] : m_idx ) { + for (const auto& [key, rowinds] : m_idx) { // key is a _row_proxy into the original frame // rowinds is a vector of row indices into the original frame - // now we iterate the frame columns, performing all operations - aggregate_column<0, Ops...>( rowinds, result_columns ); - aggregate_count( rowinds, result_columns ); - ifr.push_back( key ); + // now we iterate the frame columns, performing all operations + aggregate_column<0, Ops...>(rowinds, result_columns); + aggregate_count(rowinds, result_columns); + ifr.push_back(key); } - auto result = add_result_series<0>( ifr, result_columns ); + auto result = add_result_series<0>(ifr, result_columns); return result; } private: template std::string - get_op_name( detail::sum_op ) const + get_op_name(detail::sum_op) const { return "sum"; } template std::string - get_op_name( detail::min_op ) const + get_op_name(detail::min_op) const { return "min"; } template std::string - get_op_name( detail::max_op ) const + get_op_name(detail::max_op) const { return "max"; } template std::string - get_op_name( detail::mean_op ) const + get_op_name(detail::mean_op) const { return "mean"; } template std::string - get_op_name( detail::stddev_op ) const + get_op_name(detail::stddev_op) const { return "stddev"; } - template + template void - aggregate_rename_result_columns( std::tuple...>& result_columns ) const + rename_result_columns_args(std::tuple...>& result_columns) const { - aggregate_rename_result_columns_args<0, ColInd, Ops...>( result_columns ); - if constexpr (ColInd+1 < sizeof...(Ts)) { - aggregate_rename_result_columns( result_columns ); + rename_result_columns_args_cols<0, ArgInd, Ops...>(result_columns); + rename_result_columns_args_count(result_columns); + if constexpr (ArgInd + 1 < sizeof...(Ops)) { + rename_result_columns_args(result_columns); } } - template + template void - aggregate_rename_result_columns_args( std::tuple...>& result_columns ) const + rename_result_columns_args_count(std::tuple...>& result_columns) const + { + using Op = typename detail::pack_element::type; + if constexpr (std::is_same::value) { + auto& s = std::get(result_columns); + s.set_name("count(*)"); + } + } + + template + void + rename_result_columns_args_cols(std::tuple...>& result_columns) const { using OpsTup = std::tuple; if constexpr (detail::is_colind_at_argind::value) { columnindex ci; auto name = m_frame.column_name(ci); - auto& s = std::get(result_columns); - using Op = typename detail::pack_element::type; + auto& s = std::get(result_columns); + using Op = typename detail::pack_element::type; Op op; std::stringstream ss; ss << get_op_name(op) << "( " << name << " )"; - s.set_name( ss.str() ); + s.set_name(ss.str()); } - if constexpr (ArgInd+1 < sizeof...(Ops)) { - aggregate_rename_result_columns_args( - result_columns ); + if constexpr (ColInd + 1 < sizeof...(Ts)) { + rename_result_columns_args_cols(result_columns); } } template void - aggregate_count( const std::vector& rowinds, - std::tuple...>& result_columns - ) const + aggregate_count( + const std::vector& rowinds, std::tuple...>& result_columns) const { - aggregate_count_arg<0, Ops...>( rowinds, result_columns ); + aggregate_count_arg<0, Ops...>(rowinds, result_columns); } template void - aggregate_count_arg( const std::vector& rowinds, - std::tuple...>& result_columns - ) const + aggregate_count_arg( + const std::vector& rowinds, std::tuple...>& result_columns) const { - - if constexpr (ArgInd+1 < sizeof...(Ops)) { - aggregate_count_arg( rowinds, result_columns ); + using Op = typename detail::pack_element::type; + if constexpr (std::is_same::value) { + auto& s = std::get(result_columns); + s.push_back(rowinds.size()); + } + if constexpr (ArgInd + 1 < sizeof...(Ops)) { + aggregate_count_arg(rowinds, result_columns); } } template void - aggregate_column( const std::vector& rowinds, - std::tuple...>& result_columns - ) const + aggregate_column( + const std::vector& rowinds, std::tuple...>& result_columns) const { - aggregate_column_arg( rowinds, result_columns ); - if constexpr (ColInd+1 < sizeof...(Ts)) { - aggregate_column( rowinds, result_columns ); + aggregate_column_arg(rowinds, result_columns); + if constexpr (ColInd + 1 < sizeof...(Ts)) { + aggregate_column(rowinds, result_columns); } } template void - aggregate_column_arg( const std::vector& rowinds, - std::tuple...>& result_columns - ) const + aggregate_column_arg( + const std::vector& rowinds, std::tuple...>& result_columns) const { (void)result_columns; using OpsTup = std::tuple; - if constexpr ( detail::is_colind_at_argind::value ) { + if constexpr (detail::is_colind_at_argind::value) { using Op = typename detail::pack_element::type; Op op; - auto& result_column = std::get( result_columns ); - aggregate_column_arg_op( op, rowinds, result_column ); - + auto& result_column = std::get(result_columns); + aggregate_column_arg_op(op, rowinds, result_column); } - if constexpr (ArgInd+1 < sizeof...(Us)) { - aggregate_column_arg( rowinds, result_columns ); + if constexpr (ArgInd + 1 < sizeof...(Us)) { + aggregate_column_arg(rowinds, result_columns); } } template void - aggregate_column_arg_op( detail::sum_op, - const std::vector& rowinds, - series& result_column ) const + aggregate_column_arg_op( + detail::sum_op, const std::vector& rowinds, series& result_column) const { T temp = static_cast(0); columnindex ci; - for ( size_t rowind : rowinds ) { - const auto& row = m_frame[rowind]; - const T& t = row.at( ci ); + for (size_t rowind : rowinds) { + const auto& row = m_frame[rowind]; + const T& t = row.at(ci); temp += t; } result_column.push_back(temp); @@ -589,51 +584,48 @@ class grouped_frame, Ts...> template void - aggregate_column_arg_op( detail::max_op, - const std::vector& rowinds, - series& result_column ) const + aggregate_column_arg_op( + detail::max_op, const std::vector& rowinds, series& result_column) const { using std::max; using std::numeric_limits; T temp = numeric_limits::lowest(); columnindex ci; - for ( size_t rowind : rowinds ) { - const auto& row = m_frame[rowind]; - const T& t = row.at( ci ); - temp = max( temp, t ); + for (size_t rowind : rowinds) { + const auto& row = m_frame[rowind]; + const T& t = row.at(ci); + temp = max(temp, t); } result_column.push_back(temp); } template void - aggregate_column_arg_op( detail::min_op, - const std::vector& rowinds, - series& result_column ) const + aggregate_column_arg_op( + detail::min_op, const std::vector& rowinds, series& result_column) const { using std::min; using std::numeric_limits; T temp = numeric_limits::max(); columnindex ci; - for ( size_t rowind : rowinds ) { - const auto& row = m_frame[rowind]; - const T& t = row.at( ci ); - temp = min( temp, t ); + for (size_t rowind : rowinds) { + const auto& row = m_frame[rowind]; + const T& t = row.at(ci); + temp = min(temp, t); } result_column.push_back(temp); } template void - aggregate_column_arg_op( detail::mean_op, - const std::vector& rowinds, - series& result_column ) const + aggregate_column_arg_op( + detail::mean_op, const std::vector& rowinds, series& result_column) const { T temp = static_cast(0); columnindex ci; - for ( size_t rowind : rowinds ) { - const auto& row = m_frame[rowind]; - const T& t = row.at( ci ); + for (size_t rowind : rowinds) { + const auto& row = m_frame[rowind]; + const T& t = row.at(ci); temp += t; } temp /= rowinds.size(); @@ -642,51 +634,52 @@ class grouped_frame, Ts...> template void - aggregate_column_arg_op( detail::stddev_op, - const std::vector& rowinds, - series& result_column ) const + aggregate_column_arg_op(detail::stddev_op, const std::vector& rowinds, + series& result_column) const { T sum = static_cast(0); columnindex ci; - for ( size_t rowind : rowinds ) { - const auto& row = m_frame[rowind]; - const T& t = row.at( ci ); + for (size_t rowind : rowinds) { + const auto& row = m_frame[rowind]; + const T& t = row.at(ci); sum += t; } T mean = sum / rowinds.size(); T sqdist = static_cast(0); - for ( size_t rowind : rowinds ) { - const auto& row = m_frame[rowind]; - const T& t = row.at( ci ); - T dist = t-mean; + for (size_t rowind : rowinds) { + const auto& row = m_frame[rowind]; + const T& t = row.at(ci); + T dist = t - mean; sqdist += (dist * dist); } - - T stddev = static_cast(sqrt( sqdist / rowinds.size() )); + + T stddev = static_cast(sqrt(sqdist / rowinds.size())); result_column.push_back(stddev); } template uframe - add_result_series( typename get_index_frame::type ifr, std::tuple...>& result_columns ) const + add_result_series( + typename get_index_frame::type ifr, std::tuple...>& result_columns) const { uframe ufr = ifr; std::vector us; - vectorize_result_columns<0>( result_columns, us ); - for ( auto s : us ) { - ufr.add_series( s ); + vectorize_result_columns<0>(result_columns, us); + for (auto s : us) { + ufr.add_series(s); } return ufr; } template void - vectorize_result_columns( std::tuple...>& result_columns, std::vector& us ) const + vectorize_result_columns( + std::tuple...>& result_columns, std::vector& us) const { - us.push_back( std::get( result_columns ) ); - if constexpr (Ind+1 < sizeof...(Us)) { - vectorize_result_columns( result_columns, us ); + us.push_back(std::get(result_columns)); + if constexpr (Ind + 1 < sizeof...(Us)) { + vectorize_result_columns(result_columns, us); } } @@ -702,7 +695,7 @@ class grouped_frame, Ts...> m_idx.reserve(ifr.size()); for (size_t i = 0; i < ifr.size(); ++i) { - auto row = ifr[i]; + auto row = ifr[i]; auto findit = m_idx.find(row); if (findit == m_idx.end()) { map_value_type arr; @@ -734,7 +727,6 @@ class grouped_frame, Ts...> } private: - mutable map_type m_idx; frame m_frame; }; diff --git a/mainframe/missing.hpp b/mainframe/missing.hpp index d95b862..ecb4a5d 100644 --- a/mainframe/missing.hpp +++ b/mainframe/missing.hpp @@ -1,4 +1,3 @@ - // Copyright Ted Middleton 2022. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -7,6 +6,7 @@ #ifndef INCLUDED_mainframe_missing_hpp #define INCLUDED_mainframe_missing_hpp +#include #include namespace mf diff --git a/mainframe/series.hpp b/mainframe/series.hpp index 962bb9d..1bea763 100644 --- a/mainframe/series.hpp +++ b/mainframe/series.hpp @@ -1,4 +1,3 @@ - // Copyright Ted Middleton 2022. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/mainframe/series_vector.hpp b/mainframe/series_vector.hpp index 8593865..0ddb847 100644 --- a/mainframe/series_vector.hpp +++ b/mainframe/series_vector.hpp @@ -1,4 +1,3 @@ - // Copyright Ted Middleton 2022. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -257,7 +256,7 @@ template class series_vector : public iseries_vector { static constexpr bool is_move_constructible = std::is_move_constructible::value; - static constexpr bool is_move_assignable = std::is_move_assignable::value; + static constexpr bool is_move_assignable = std::is_move_assignable::value; public: static const size_t DEFAULT_SIZE = 32; diff --git a/mainframe/simd.hpp b/mainframe/simd.hpp index 92e8d83..53e0498 100644 --- a/mainframe/simd.hpp +++ b/mainframe/simd.hpp @@ -1,4 +1,3 @@ - // Copyright Ted Middleton 2022. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at diff --git a/tests/mainframe_test_main.cpp b/tests/mainframe_test_main.cpp index c8bac5c..27fa0b1 100644 --- a/tests/mainframe_test_main.cpp +++ b/tests/mainframe_test_main.cpp @@ -1,4 +1,3 @@ - // Copyright Ted Middleton 2022. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at @@ -1488,47 +1487,31 @@ TEST_CASE("aggregate", "[frame]") dout << "f1:\n"; dout << f1; - auto gf = f1.groupby(_0, _1); - - // start with groupby( _5, _6 ).aggregate( sum( _1 ), sum( _2 ), count(), min( _4 ), sum( _3 ), sum( _1 ), max( _1 ) ) - using F = frame; - using RCFA = typename mf::detail::get_result_columns_from_args::type; + auto gf = f1.groupby(_0, _1); + + // start with groupby( _5, _6 ).aggregate( sum( _1 ), sum( _2 ), count(), min( _4 ), sum( _3 ), + // sum( _1 ), max( _1 ) ) + using F = frame; + using RCFA = typename mf::detail::get_result_columns_from_args::type; RCFA rcfa; (void)rcfa; - //TD foo; + // TD foo; using AF = typename mf::detail::get_aggregate_frame, - decltype(mf::agg::sum(_0)), - decltype(mf::agg::sum(_1)), - decltype(mf::agg::count()), - decltype(mf::agg::min(_3)), - decltype(mf::agg::sum(_2)), - decltype(mf::agg::sum(_0)), - decltype(mf::agg::max(_0)) - >::type; + decltype(mf::agg::sum(_0)), decltype(mf::agg::sum(_1)), decltype(mf::agg::count()), + decltype(mf::agg::min(_3)), decltype(mf::agg::sum(_2)), decltype(mf::agg::sum(_0)), + decltype(mf::agg::max(_0))>::type; AF af; (void)af; - //TD foo4; - using TUP = tuple< - decltype(mf::agg::sum(_0)), - decltype(mf::agg::sum(_1)), - decltype(mf::agg::count()), - decltype(mf::agg::min(_3)), - decltype(mf::agg::sum(_2)), - decltype(mf::agg::sum(_0)), - decltype(mf::agg::max(_0)) - >; + // TD foo4; + using TUP = tuple; TUP tup; (void)tup; - //TD foo6; + // TD foo6; REQUIRE(mf::detail::is_colind_at_argind<0, 0, TUP>::value == true); REQUIRE(mf::detail::is_colind_at_argind<1, 1, TUP>::value == true); REQUIRE(mf::detail::is_colind_at_argind<3, 3, TUP>::value == true); @@ -1552,25 +1535,31 @@ TEST_CASE("aggregate", "[frame]") REQUIRE(mf::detail::is_colind_at_argind<6, 2, TUP>::value == false); gf.build_index(); - auto f2 = gf.aggregate( - agg::sum( _2 ), - agg::min( _2 ), - agg::max( _2 ), - agg::mean( _2 ), - agg::stddev( _2 ) ); + auto f2 = gf.aggregate( + agg::sum(_2), agg::min(_2), agg::max(_2), agg::mean(_2), agg::stddev(_2), agg::count()); dout << f2; - auto f3 = gf.aggregate( - agg::sum( _3 ), - agg::min( _3 ), - agg::max( _3 ), - agg::mean( _3 ), - agg::stddev( _3 ) ); + auto f3 = gf.aggregate( + agg::sum(_3), agg::min(_3), agg::max(_3), agg::mean(_3), agg::stddev(_3), agg::count()); dout << f3; - std::sort( f2.begin(), f2.end() ); - std::sort( f3.begin(), f3.end() ); + std::sort(f2.begin(), f2.end()); + std::sort(f3.begin(), f3.end()); // rain { + // | date | temperature | sum( rain ) | min( rain ) | max( rain ) | mean( rain ) | + // stddev( rain ) | count(*) + // __|____________|_____________|_____________|_____________|_____________|______________|________________|__________ + // 0| 2022-01-01 | 1 | 0 | 0 | 0 | 0 | + // 0 | 1 1| 2022-01-02 | 2 | 3 | 1 | 2 | 1.5 + // | 0.5 | 2 2| 2022-01-03 | 3 | 9 | 2 | 4 + // | 3 | 0.816497 | 3 3| 2022-01-04 | 4 | 12 | + // 3 | 5 | 4 | 0.816497 | 3 4| 2022-01-05 | 5 | + // 15 | 4 | 6 | 5 | 0.816497 | 3 5| 2022-01-06 + // | 6 | 18 | 5 | 7 | 6 | 0.816497 + // | 3 6| 2022-01-07 | 7 | 21 | 6 | 8 | 7 | + // 0.816497 | 3 7| 2022-01-08 | 8 | 15 | 7 | 8 | 7.5 | + // 0.5 | 2 8| 2022-01-09 | 9 | 9 | 9 | 9 | + // 9 | 0 | 1 auto it = f2.cbegin(); // date REQUIRE((it + 0)->at(_0) == 2022_y / 1 / 1); @@ -1604,7 +1593,7 @@ TEST_CASE("aggregate", "[frame]") REQUIRE((it + 6)->at(_2) == 21); REQUIRE((it + 7)->at(_2) == 15); REQUIRE((it + 8)->at(_2) == 9); - + // min( rain ) REQUIRE((it + 0)->at(_3) == 0); REQUIRE((it + 1)->at(_3) == 1); @@ -1626,7 +1615,7 @@ TEST_CASE("aggregate", "[frame]") REQUIRE((it + 6)->at(_4) == 8); REQUIRE((it + 7)->at(_4) == 8); REQUIRE((it + 8)->at(_4) == 9); - + // mean( rain ) REQUIRE((it + 0)->at(_5) == 0); REQUIRE((it + 1)->at(_5) == 1.5); @@ -1637,7 +1626,7 @@ TEST_CASE("aggregate", "[frame]") REQUIRE((it + 6)->at(_5) == 7); REQUIRE((it + 7)->at(_5) == 7.5); REQUIRE((it + 8)->at(_5) == 9); - + // stddev( rain ) REQUIRE((it + 0)->at(_6) == Approx(0)); REQUIRE((it + 1)->at(_6) == Approx(0.5)); @@ -1648,11 +1637,36 @@ TEST_CASE("aggregate", "[frame]") REQUIRE((it + 6)->at(_6) == Approx(0.816497)); REQUIRE((it + 7)->at(_6) == Approx(0.5)); REQUIRE((it + 8)->at(_6) == Approx(0)); - } + // count() + REQUIRE((it + 0)->at(_7) == 1); + REQUIRE((it + 1)->at(_7) == 2); + REQUIRE((it + 2)->at(_7) == 3); + REQUIRE((it + 3)->at(_7) == 3); + REQUIRE((it + 4)->at(_7) == 3); + REQUIRE((it + 5)->at(_7) == 3); + REQUIRE((it + 6)->at(_7) == 3); + REQUIRE((it + 7)->at(_7) == 2); + REQUIRE((it + 8)->at(_7) == 1); + } // humidity { + // | date | temperature | sum( humidity ) | min( humidity ) | max( humidity ) | + // mean( humidity ) | stddev( humidity ) | count(*) + // __|____________|_____________|_________________|_________________|_________________|__________________|____________________|__________ + // 0| 2022-01-01 | 1 | -5 | -5 | -5 | -5 | + // 0 | 1 1| 2022-01-02 | 2 | -10 | -5.5 | -4.5 | -5 + // | 0.5 | 2 2| 2022-01-03 | 3 | -15 | -6 | -4 + // | -5 | 0.816497 | 3 3| 2022-01-04 | 4 | -15 | + // -6 | -4 | -5 | 0.816497 | 3 4| 2022-01-05 | + // 5 | -15 | -6 | -4 | -5 | 0.816497 | + // 3 5| 2022-01-06 | 6 | -15 | -6 | -4 | -5 + // | 0.816497 | 3 6| 2022-01-07 | 7 | -15 | -6 | -4 + // | -5 | 0.816497 | 3 7| 2022-01-08 | 8 | -10 | + // -5.5 | -4.5 | -5 | 0.5 | 2 8| 2022-01-09 + // | 9 | -5 | -5 | -5 | -5 | + // 0 | 1 auto it = f3.cbegin(); // date REQUIRE((it + 0)->at(_0) == 2022_y / 1 / 1); @@ -1686,7 +1700,7 @@ TEST_CASE("aggregate", "[frame]") REQUIRE((it + 6)->at(_2) == -15); REQUIRE((it + 7)->at(_2) == -10); REQUIRE((it + 8)->at(_2) == -5); - + // min( humidity ) REQUIRE((it + 0)->at(_3) == -5); REQUIRE((it + 1)->at(_3) == -5.5); @@ -1708,7 +1722,7 @@ TEST_CASE("aggregate", "[frame]") REQUIRE((it + 6)->at(_4) == -4); REQUIRE((it + 7)->at(_4) == -4.5); REQUIRE((it + 8)->at(_4) == -5); - + // mean( humidity ) REQUIRE((it + 0)->at(_5) == -5); REQUIRE((it + 1)->at(_5) == -5); @@ -1719,7 +1733,7 @@ TEST_CASE("aggregate", "[frame]") REQUIRE((it + 6)->at(_5) == -5); REQUIRE((it + 7)->at(_5) == -5); REQUIRE((it + 8)->at(_5) == -5); - + // stddev( humidity ) REQUIRE((it + 0)->at(_6) == Approx(0)); REQUIRE((it + 1)->at(_6) == Approx(0.5)); @@ -1730,6 +1744,16 @@ TEST_CASE("aggregate", "[frame]") REQUIRE((it + 6)->at(_6) == Approx(0.816497)); REQUIRE((it + 7)->at(_6) == Approx(0.5)); REQUIRE((it + 8)->at(_6) == Approx(0)); - } + // count() + REQUIRE((it + 0)->at(_7) == 1); + REQUIRE((it + 1)->at(_7) == 2); + REQUIRE((it + 2)->at(_7) == 3); + REQUIRE((it + 3)->at(_7) == 3); + REQUIRE((it + 4)->at(_7) == 3); + REQUIRE((it + 5)->at(_7) == 3); + REQUIRE((it + 6)->at(_7) == 3); + REQUIRE((it + 7)->at(_7) == 2); + REQUIRE((it + 8)->at(_7) == 1); + } }