根据一列中的相同值合并二维向量中的行

Consolidating rows in a 2d vector with respect to same value in one column

我有一个二维向量,它有 6 列和 500 rows.I 想通过比较单个列值(PDG_ID)来组合行,即如果行的 PDG_ID 列值相同,我将取其他五列的平均值并将这些行存储为一行。 知道如何在 C++ 中做到这一点吗? 2d vectror with six columns

需要了解需求,然后select进行适配设计。

在您的情况下,您想要分组 具有相同 ID 的几行,并计算数据条目的平均值。

因此,1个ID与1个或多个数据条目之间存在关系。或者在 C++ 中,一个 ID 关联了一个或多个条目。

在 C++ 中,我们有所谓的关联容器,如 std::mapstd::unordered_map。在这里,我们可以存储一个密钥(ID)和许多关联数据。

如果我们把一行的所有数据放到一个结构体中,我们可以这样写:

struct PDG {
    int ID{};
    int status{};
    double Px{};
    double Py{};
    double Pz{};
    double E{};
}

而且,如果我们想存储与许多 PDG 关联的 ID,我们可以定义一个这样的映射:

std::map<int, std::vector<PDG>> groupedPDGs{};

在这个映射中,我们可以存储由一个或多个PDG组成的ID和关联数据。

然后我们可以添加一些非常 small/simple 的辅助函数,例如 IO 功能或计算平均值。这样我们就把大的、更复杂的问题分解成更简单的部分。

然后,整体实现可能如下所示:

#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <iterator>
#include <map>
#include <iomanip>

// Simple data struct with all necessary values and IO functions
struct PDG {

    // Data part
    int ID{};
    int status{};
    double Px{};
    double Py{};
    double Pz{};
    double E{};

    // Input of one row
    friend std::istream& operator >> (std::istream& is, PDG& pdg) {
        char c{};
        return is >> pdg.ID >> c >> pdg.status >> c >> pdg.Px >> c >> pdg.Py >> c >> pdg.Pz >> c >> pdg.E;
    }
    // Output of one row
    friend std::ostream& operator << (std::ostream& os, const PDG& pdg) {
        return os << "ID: " << std::setw(5) << pdg.ID << "\tStatus: " << pdg.status << "\tPx: " << std::setw(9) << pdg.Px 
            << "\tPy: " << std::setw(9) << pdg.Py << "\tPz: " << std::setw(9) << pdg.Pz << "\tE: " << std::setw(9) << pdg.E;
    }
};

// Alias/Abbreviation for a vector of PDGs
using PDGS = std::vector<PDG>;

// Calculate a mean value for vector of PDG data
PDG calculateMean(const PDGS& pdgs) {

    // Here we store the result. Initilize with values from first row and zeroes
    PDG result{ pdgs.front().ID, pdgs.front().status, 0.0, 0.0, 0.0, 0.0};

    // Add up data fields according to type
    for (size_t i{}; i < pdgs.size(); ++i) {
        result.Px += pdgs[i].Px;
        result.Py += pdgs[i].Py;
        result.Pz += pdgs[i].Pz;
        result.E += pdgs[i].E;
    }
    // Get mean value
    result.Px /= pdgs.size();
    result.Py /= pdgs.size();
    result.Pz /= pdgs.size();
    result.E /= pdgs.size();

    // And return result to calling function
    return result;
}

int main() {

    // Open the source file containing the data, and check, if the file could be opened
    if (std::ifstream ifs{ "pdg.txt" }; ifs) {

        // Read header line and throw away
        std::string header{}; std::getline(ifs, header);
        
        // Here we will stored the PDGs grouped by their ID
        std::map<int, PDGS> groupedPDGs{};

        // Read all source lines
        PDG pdg{};
        while (ifs >> pdg)

            // Store read values grouped by their ID
            groupedPDGs[pdg.ID].push_back(pdg);

        // Result with mean values
        PDGS result{};

        // Calculate mean values and store in additional vector
        for (const auto& [id, pdgs] : groupedPDGs)
            result.push_back(std::move(calculateMean(pdgs)));

        // Debug: Show output to user
        for (const PDG& p : result)
            std::cout << p << '\n';
    }
    std::cerr << "\nError: Could not open source datafile\n\n";
}

输入文件如:

PDG ID, Status, Px, Py, Pz, E
22, 1, 0.00658, 0.0131, -0.00395, 0.0152
13, 1, -43.2, -44.7, -49.6, 79.6
14, 1, 3.5, 21.4, 0.499, 21.7
16, 1, 41.1, -18, 27.8, 52.8
211, 1, 0.483, -0.312, 1.52, 1.63
211, 1, -0.247, -1.75, 45.2, 45.2
321, 1, 0.717, 0.982, 52.6, 52.6
321, 1, 0.112, 0.423, 33.2, 33.2
211, 1, 0.191, -0.68, -178, 178
2212, 1, 1.08, -0.428, -1.78E+03, 1.78E+03
2212, 1, 7.61, 4.28, 76.3, 76.8
211, 1, 0.176, 0.247, 8.9, 8.9
211, 1, 0.456, -0.73, 0.342, 0.937
2112, 1, 0.633, -0.904, 0.423, 1.51
2112, 1, 1, -0.645, 0.366, 1.56
211, 1, -0.0722, 0.147, -0.153, 0.264
211, 1, 0.339, 0.402, 0.304, 0.623
211, 1, 3.64, 2.58, -2.84, 5.29
211, 1, 0.307, 0.208, -5.69, 5.71
2212, 1, 0.118, 0.359, -3.29, 3.45

我们得到以下输出:

ID:    13       Status: 1       Px:     -43.2   Py:     -44.7   Pz:     -49.6   E:      79.6
ID:    14       Status: 1       Px:       3.5   Py:      21.4   Pz:     0.499   E:      21.7
ID:    16       Status: 1       Px:      41.1   Py:       -18   Pz:      27.8   E:      52.8
ID:    22       Status: 1       Px:   0.00658   Py:    0.0131   Pz:  -0.00395   E:    0.0152
ID:   211       Status: 1       Px:  0.585867   Py: 0.0124444   Pz:  -14.4908   E:   27.3949
ID:   321       Status: 1       Px:    0.4145   Py:    0.7025   Pz:      42.9   E:      42.9
ID:  2112       Status: 1       Px:    0.8165   Py:   -0.7745   Pz:    0.3945   E:     1.535
ID:  2212       Status: 1       Px:     2.936   Py:   1.40367   Pz:  -568.997   E:   620.083