2

如果我有这样的 python 数据表:

from datatable import f, dt
data = dt.Frame(grp=["a","a","b","b","b","b","c"], value=[2,3,1,2,5,9,2])

如何按组创建具有行号的新列?也就是说,什么是 R 的等价data.table

data[, id:=1:.N, by=.(grp)]

这行得通,但似乎完全荒谬

data['id'] = np.concatenate(
                [np.arange(x)
                    for x in data[:,dt.count(), dt.by(f.grp)]['count'].to_numpy()])

所需的输出:

   | grp    value     id
   | str32  int32  int64
-- + -----  -----  -----
 0 | a          2      0
 1 | a          3      1
 2 | b          1      0
 3 | b          2      1
 4 | b          5      2
 5 | b          9      3
 6 | c          2      0
4

2 回答 2

2

一种方法是转换to_pandasgroupby(在 pandas DataFrame 上)并使用cumcount

import datatable as dt

data = dt.Frame(grp=["a", "a", "b", "b", "b", "b", "c"], value=[2, 3, 1, 2, 5, 9, 2])

data["id"] = data.to_pandas().groupby("grp").cumcount()
print(data)

输出

   | grp    value     id
   | str32  int32  int64
-- + -----  -----  -----
 0 | a          2      0
 1 | a          3      1
 2 | b          1      0
 3 | b          2      1
 4 | b          5      2
 5 | b          9      3
 6 | c          2      0
[7 rows x 3 columns]
于 2021-10-18T21:34:46.610 回答
2

datatable没有累积计数功能,事实上目前任何聚合都没有累积功能。

一种可能提高速度的方法是使用更快的 numpy 迭代,其中 for 循环在 C 中完成,并且效率更高。代码来自此处并为此目的进行了修改:

from datatable import dt, f, by
import numpy as np

In [244]: def create_ranges(indices):
     ...:     cum_length = indices.cumsum()
     ...:     ids = np.ones(cum_length[-1], dtype=int)
     ...:     ids[0] = 0
     ...:     ids[cum_length[:-1]] = -1 * indices[:-1] + 1
     ...:     return ids.cumsum()


counts =  data[:, dt.count(), by('grp', add_columns=False)].to_numpy().ravel()
data[:, f[:].extend({"counts" : create_ranges(counts)})]

   | grp    value  counts
   | str32  int32   int64
-- + -----  -----  ------
 0 | a          2       0
 1 | a          3       1
 2 | b          1       0
 3 | b          2       1
 4 | b          5       2
 5 | b          9       3
 6 | c          2       0
[7 rows x 3 columns]

create_ranges 函数很棒(建立在 cumsum 上的逻辑很好)并且随着数组大小的增加而真正发挥作用。

当然,这有其缺点;您正在走出数据表进入 numpy 领域,然后回到数据表;另一方面是我依赖于这些组是按词汇排序的事实;如果数据未排序(并且必须在分组列上排序),这将不起作用。

初步测试显示速度显着提高;同样,它的范围有限,如果将其纳入数据表库中会更容易/更好。

如果你精通 C++,你可以考虑将这个函数贡献给库;我和其他许多人都会感谢你的努力。

你可以看看 pypolars 看看它是否对你的用例有帮助。从 h2o 基准测试来看,它看起来是一个非常快速的工具。

于 2021-10-22T00:05:47.657 回答