【问题标题】:How to find the column-wise unique elements, and their frequencies, of a 2d array如何找到二维数组的按列唯一元素及其频率
【发布时间】:2020-04-12 14:28:41
【问题描述】:

目前,我正在使用 pandas 查找二维数组的按列唯一元素及其频率:

#Dummy array 
arr = [[0,-1,0,0,0,1,0],[1,0,0,0,0,-1,0],[0,0,0,0,0,0,-1]]

#Convert to pandas
pd_arr = pd.DataFrame(arr)

#Apply value_counts on each column
val_counts = pd_arr.apply(pd.value_counts)

这会产生数据框:

这正是我想要的 - 在这里,索引代表唯一值,并且表格填充了这些值在虚拟数组中 7 列中的每一列中的频率。

实际上,arr 是 40x8 并包含 -1、1 和 0 值 - 这并不大,但位于数十万个循环内。整个循环花费的时间太长,所以我正在为每个部分寻找更快的方法。

经过长时间的搜索,我似乎找不到不使用 pandas 的方法。使用 numpy 数组而不是转换为 pandas 来寻找解决方案可能是理想的,因为直接使用 numpy 会使我的循环的其他部分更快得多,并且在 pandas 和 numpy 之间切换听起来也不是很干净整洁。不过,我也愿意接受更快的 pandas 选项!

我已经尝试使用 np.unique np.unique(arr) 之类的东西解决 arr 问题

但是,这个,以及我在操纵它的失败尝试,只给出了唯一值 array([-1, 0, 1]) 和整个数组的总频率,没有像上面示例输出中那样跨轴执行此操作的灵活性。

似乎没有太多其他方法可以解决这个特定问题,但是如果我错了,请指导我!

实际上,arr 是 40x8 并包含 -1、1 和 0 值 - 我知道这并不大,但它位于数十万个循环中,所以它所花费的时间加起来!

我很想听听您对如何找到这些独特价值及其重要性的建议!我可以使用的模块不受限制。谢谢:)

【问题讨论】:

  • pd_arr.transform(pd.value_counts) 也会得到相同的结果。检查它是否有助于计时。
  • “坐在几十万的循环中”究竟是什么意思?您可以制作一个形状为(40, 8, several hundred thousand) 的数据集,还是希望单独处理每个迭代?
  • 感谢回复,我会用transform查看时间。
  • 对不起,我的意思是我正在运行循环 600,000 次,这只是循环的一部分,所以我希望单独处理它

标签: python arrays pandas numpy dataframe


【解决方案1】:

利用只有三个值 -1,0,1 的优势,您可以使用以下代码在我相当普通的笔记本电脑上为 40x8 数组使用 23 us(比 pandas 方法加速 > 500 倍):

def count_it(a):
    total = a.shape[0]
    non_0 = np.count_nonzero(a,axis=0)
    delta = a.sum(0)
    return np.array([(non_0-delta)>>1,total-non_0,(non_0+delta)>>1])

这将返回实际计数,如果您希望 nan 指示计数为 0,则必须将 0 替换为 nans。

例子:

a = np.random.randint(-1,2,(40,8)) 

count_it(a)
# array([[12, 12,  8, 12, 14, 12, 16, 12],
#        [15, 11, 20, 17, 11, 11, 11, 14],
#        [13, 17, 12, 11, 15, 17, 13, 14]])

# check against pandas:
np.all(pd.DataFrame(a).apply(pd.value_counts) == count_it(a))
# True

它是如何工作的:

让我们考虑单个列 C 并让 m,z,p 是 -1s 0s 和 1s 的计数。那么

  1. m+z+p = len(C)
  2. m+p = np.count_nonzero(C)
  3. p-m = C.sum()

我们可以——而且代码确实可以——为 m、z 和 p 解决这个问题。

【讨论】:

  • 感谢您的回复,我知道您在做什么,我认为这将有很大帮助!只是想弄清楚输入类型不支持错误'ufunc'right_shift',并且根据强制转换规则''safe'''无法安全地将输入强制转换为任何支持的类型,我会接受你的回答。不过,我认为这是我的问题!
  • 快速提问,有没有办法知道 -1,0,1 值是否根本没有出现在任何列中? IE。现在我得到一个 3 行 8 列的数组,如果我只得到 2 行 8 列的结果,有没有办法知道哪个值没有出现?
  • @SophieMayne 您可以用除以 2(“//2”或“/2”或“*0.5”)替换右移一(“>>1”)。缺失值将导致计数为 0 查找 0,您将知道哪些值没有出现。总会有三行。
猜你喜欢
  • 2021-07-20
  • 2021-02-27
  • 2021-03-15
  • 1970-01-01
  • 1970-01-01
  • 2021-02-03
  • 2020-11-02
  • 1970-01-01
  • 2013-03-26
相关资源
最近更新 更多