用C ++构建数据框

时间:2019-08-29 00:30:06

标签: c++ dataframe pointers

我正在尝试用C ++构建一个DataFrame。我面临一些问题,例如处理可变数据类型。

我正在考虑受Pandas DataFrame(来自python)启发的DataFrame。所以我的设计思路是:

  1. 构建对象“系列”,该对象是固定数据类型的向量。
  2. 构建一个对象“ DataFrame”,该对象将存储系列列表(此列表可以是可变的)。

项目1.只是一个常规向量。因此,例如,用户会致电

Series.fill({1,2,3,4}),它将矢量{1,2,3,4}存储在Series的某些属性中,例如Series.data。

问题1.如何将一个将{1,2,3,4}理解为4个整数的向量的类。有可能吗?

下一个问题是:

关于2.,我可以看到DataFrame是n列和m行的矩阵,但是这些列可以具有不同的数据类型。

我试图将其设计为n个指针的向量,其中每个指针将指向具有不同数据类型的维m的向量。

我试图做类似的事情

vector<void*> columns(10)

并用类似的东西填充

columns[0] = (int*) malloc(8*sizeof(int))

但是,如果我尝试填充矢量,这是行不通的

(*columns[0])[0] = 5;

我收到错误

::value_type {aka void*}’ is not a pointer-to-object type (int *) (*a[0])[0] = 5;

如何正确执行?我还有其他问题,例如,如何将数量不确定的Series附加到DataFrame中,但就目前而言,仅使用具有不同数据类型的列构建矩阵是一个很好的开始。

我知道我必须跟踪我的void向量中的指针类型,但是我可以创建一个包含所有数据类型的并行列表,并将其设置为类DataFrame的属性。

2 个答案:

答案 0 :(得分:1)

在C ++中构建异构容器(应该是一个数据框)比您想象的要复杂,因为C ++是静态类型的。这意味着您必须在编译时知道所有类型。 您的方法使用了一个指针向量(该方法有一些变体,我将不再赘述)。这种方法效率很低,因为指针指向整个内存,并破坏了缓存的位置。我什至不建议您尝试实现这种数据框,因为确实没有意义。

看一下C ++中DataFrame的这种实现:https://github.com/hosseinmoein/DataFrame。您也许可以按原样使用它。或从中了解如何实现真正的异构DataFrame。它使用哈希表中的静态向量集合来实现真正的异构容器。它还使用连续的内存空间,从而避免了指针效应。

答案 1 :(得分:0)

TL; DR版本

丢弃您在做什么。

使用vector<vector<int>> columns;。当您需要一列时,请使用columns[index].data()index ed内部vector获取指向后备数组的指针,并将该int *传递给所需的{{1} }。 void *将被隐式转换。

说明

Quoting cppreference

  

int *-输入一组空值。这是一个incomplete type,无法完成(因此,不允许使用void类型的对象)。没有arrays的空白,也没有references的空白。但是,允许pointers to void和返回类型为void的函数(其他语言的过程)。

由于无效是不完整的,因此您不能拥有void。必须先将void强制转换回实际的数据类型void*,然后才能将其用于除传递匿名键入的指针以外的其他任何类型。 int*的所有接收者都必须知道除了传递它以外,对它执行任何操作实际上是什么。

需要void *参数的函数将获取您赋予它们的任何指针,而无需您的任何进一步工作,因此几乎不需要在C ++中制作void *变量。几乎所有需要使用void *的情况都充满了多态性或模板。上一次我在C ++中使用void *时是当我用附加的类将C ++编写为C时回来的。

错误

给出

void *

每个元素将包含一个vector<void*> columns(10); s数组,让我们来研究一下

int

逐步查看我们拥有的类型,并确保每个步骤中的类型都一致

(*columns[0])[0] = 5;

获取columns[0] 中的第一个元素vector。到目前为止一切顺利。

void*

*columns[0] 处取消引用void*。如前言所述,这是无法完成的。您不能取消引用columns[0],因为您拥有类型void *的值,这会产生报告的 :: value_type {aka void }'不是指向对象的指针类型* 错误信息。

我们可以

void

将其转换为指向*reinterpret_cast<int*>(columns[0]) 的指针,我们可以取消引用并匹配初始类型,然后接收int,特别是数组中的第一个int。

int

将失败,因为您无法为(*reinterpret_cast<int*>(columns[0]))[0] 编制索引。这就像编写int。这意味着取消引用是不必要的。

最终结果应类似于

42[0]

但是不要这样做。这是不必要的,而且过于复杂。