簡體   English   中英

查找數據集模式的更好方法C ++

[英]Better way to find the mode of a data set C++

我正在嘗試查找C ++中數據集的模式。 我寫了一個似乎可以做到的函數,但是我不喜歡在沒有模式的情況下必須返回一個空向量。 有沒有更有效的方法可以做到這一點? 這是我的代碼:

vector<double> findMode(vector<double> v)
{
    map<double, int> modeStorage;
    vector<double> mode;
    int mostRepetitions = 2;
    for (double i : v)
    {
        ++modeStorage[i];
    }
    for (map<double, int>::iterator it = modeStorage.begin(); it != modeStorage.end(); ++it)
    {
        if (it->second >= mostRepetitions)
        {
            mostRepetitions = it->second;
        }
    }
    for (map<double, int>::iterator it = modeStorage.begin(); it != modeStorage.end(); ++it)
    {
        if (it->second == mostRepetitions)
        {
          mode.push_back(it->first);
        }
    }
return mode;
}

提前致謝。

編輯:只是為了澄清:如果數據集中的任何一個值中至少沒有兩個相同的值,則沒有模式。 這就是為什么mostRepetitions必須大於等於2的原因。如果函數發現沒有模式(所有值在集合中僅存在一次),那么它將返回一個空向量。 那是我的問題。 從函數取回向量后,我必須測試向量是否為空,這讓我感到草率(如果不是,請告訴我,我會閉嘴)。

我編寫了一個片段,使用了一些不同的方法:1)如果獲得沒有模式的向量,則會引發異常。 2)我們只返回模式。 3)該函數是模板,但您可以用T代替您的類型。

我試圖在評論中解釋該算法。

OBS:有一些lambda可以幫助我編寫測試,它們需要C ++ 11支持。 如果您不知道或不知道,請關注T findMode(const std::vector<T>& vec )

#include<vector>
#include<algorithm>
#include<string>
#include<stdexcept>

#include<iostream>


template<typename T>
T findMode(const std::vector<T>& vec ){

    if(vec.size() == 0){
        throw std::domain_error("No mode for empty vector");
    }
    else if(vec.size() == 1)
        return vec[0];

    // copy the original, don´t alter the input
    std::vector<T> v(vec); 

    // Order just to group same elements
    // T MUST implement '>' operator. Which is trivial
    // for primitive types.
    std::sort(v.begin(), v.end());  

    typename std::vector<T>::iterator it ; 

    it = v.begin(); 

    size_t largest_count = 0;
    T mode;
    bool flag = false; // this flag indicates when we found 2 equal modes
    while( it != v.end() ){

        T m = *it;
        size_t count = 1;

        while( it != v.end() && *++it == m ){   
            count++;            
        }   

        if(count > largest_count){
            largest_count = count;
            mode = m;
            flag = false;
        }
        else if(count == largest_count){
            flag = true;
        }
    }

    if(flag){
        // if we found a count as large as the largest, 
        // we have no made, so, throw exception
        throw std::domain_error("No mode for vector");
    }

    return mode;    
}

template<typename T>
bool test(const std::vector<T> v, const T& expected_mode){
    T mode;
    try{
        return findMode<T>(v) == expected_mode;
    }catch(const std::domain_error& de){
        return false;
    } 
}

int main(){


    const std::vector<int> vec_int = {1};
    std::cout << [&](){ return test<int>(vec_int, 1) == true ? "OK" : "NOK"; }() << " for {1}" 
        << std::endl;

    // This test is OK, if returns false, there is no mode
    const std::vector<int> vec_int2 = {1,1,2,2};
    std::cout << [&](){ return test<int>(vec_int2, 1) == false ? "OK" : "NOK"; }() 
        << " for {1,1,2,2}" << std::endl;

    // This test is OK, if returns false, there is no mode
    const std::vector<int> vec_int3 = {1,1,1,1};
    std::cout << [&](){ return test<int>(vec_int3, 1) == true ? "OK" : "NOK"; }() 
        << " for {1,1,1,1}" << std::endl;

    // This test is OK, if returns false, there is no mode
    const std::vector<double> vec_double = {6.25, 1.1, 1.1, 2.2, 2.3, 2.5, 6.25, 6.25, 6.25, 6};
    std::cout << [&](){ return test<double>(vec_double, 6.25) == true ? "OK" : "NOK"; }() 
        << " for {6.25, 1.1, 1.1, 2.2, 2.3, 2.5, 6.25, 6.25, 6.25, 6}" << std::endl;


    // This test is OK, if returns false, there is no mode
    const std::vector<char> vec_char ={'0', 'X', 'D', 'E', 'A', 'D', 'B', 'E', 'E', 'F'};
    std::cout << [&](){ return test<char>(vec_char, 'E') == true ? "OK" : "NOK"; }()
        << " for {'0', 'X', 'D', 'E', 'A', 'D', 'B', 'E', 'E', 'F'}" << std::endl;


    return 0;   
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM