Python:计算 numpy 数组(大型数据集)中出现次数的更快方法
Python: faster way of counting occurences in numpy arrays (large dataset)
我是 Python 的新手。我有一个 numpy.array
,大小为 66049x1
(66049 行和 1 列)。这些值从小到大排序,属于 float
类型,其中一些值是重复的。
我需要确定每个值出现的频率(给定值等于但未超过的次数,例如X<=x在统计术语 ) 中,以便稍后绘制样本累积分布函数。
我目前使用的代码如下,但是非常慢,因为它要循环66049x66049=4362470401
次。有什么办法可以提高这段代码的速度吗?使用 dictionaries
可能会有任何帮助吗?不幸的是,我无法更改正在使用的数组的大小。
+++Function header+++
...
...
directoryPath=raw_input('Directory path for native csv file: ')
csvfile = numpy.genfromtxt(directoryPath, delimiter=",")
x=csvfile[:,2]
x1=numpy.delete(x, 0, 0)
x2=numpy.zeros((x1.shape[0]))
x2=sorted(x1)
x3=numpy.around(x2, decimals=3)
count=numpy.zeros(len(x3))
#Iterates over the x3 array to find the number of occurrences of each value
for i in range(len(x3)):
temp=x3[i]
for j in range(len(x3)):
if (temp<=x3[j]):
count[j]=count[j]+1
#Creates a 2D array with (value, occurrences)
x4=numpy.zeros((len(x3), 2))
for i in range(len(x3)):
x4[i,0]=x3[i]
x4[i,1]=numpy.around((count[i]/x1.shape[0]),decimals=3)
...
...
+++Function continues+++
你应该使用np.where
,然后计算得到的索引向量的长度:
indices = np.where(x3 <= value)
count = len(indices[0])
import numpy as np
import pandas as pd
from collections import Counter
import matplotlib.pyplot as plt
arr = np.random.randint(0, 100, (100000,1))
df = pd.DataFrame(arr)
cnt = Counter(df[0])
df_p = pd.DataFrame(cnt, index=['data'])
df_p.T.plot(kind='hist')
plt.show()
整个脚本为 (100,000x1)
数组执行 (~2s) 的时间非常短。我没有计时,但如果您提供执行您的脚本所花费的时间,我们可以进行比较。
我使用 collections
to count the number of occurrences, my experiences with it have always been great (timewise). I converted it into DataFrame
中的 [Counter][2]
进行绘图并使用 T
进行转置。
您的数据确实有点重复,但您可以尝试进一步优化它。事实上,它非常快。
编辑
使用 cumsum()
创建 CDF
import numpy as np
import pandas as pd
from collections import Counter
import matplotlib.pyplot as plt
arr = np.random.randint(0, 100, (100000,1))
df = pd.DataFrame(arr)
cnt = Counter(df[0])
df_p = pd.DataFrame(cnt, index=['data']).T
df_p['cumu'] = df_p['data'].cumsum()
df_p['cumu'].plot(kind='line')
plt.show()
编辑 2
对于 scatter()
绘图,您必须明确指定 (x,y)。此外,调用 df_p['cumu']
将导致 Series
,而不是 DataFrame
。
要正确显示散点图,您需要以下内容:
import numpy as np
import pandas as pd
from collections import Counter
import matplotlib.pyplot as plt
arr = np.random.randint(0, 100, (100000,1))
df = pd.DataFrame(arr)
cnt = Counter(df[0])
df_p = pd.DataFrame(cnt, index=['data']).T
df_p['cumu'] = df_p['data'].cumsum()
df_p.plot(kind='scatter', x='data', y='cumu')
plt.show()
如果效率很重要,您可以使用 numpy 函数 bincount,它需要整数:
import numpy as np
a=np.random.rand(66049).reshape((66049,1)).round(3)
z=np.bincount(np.int32(1000*a[:,0]))
大约需要1ms。
此致。
# for counting a single value
mask = (my_np_array == value_to_count).astype('uint8')
# or a condition
mask = (my_np_array <= max_value).astype('uint8')
count = np.sum(mask)
我是 Python 的新手。我有一个 numpy.array
,大小为 66049x1
(66049 行和 1 列)。这些值从小到大排序,属于 float
类型,其中一些值是重复的。
我需要确定每个值出现的频率(给定值等于但未超过的次数,例如X<=x在统计术语 ) 中,以便稍后绘制样本累积分布函数。
我目前使用的代码如下,但是非常慢,因为它要循环66049x66049=4362470401
次。有什么办法可以提高这段代码的速度吗?使用 dictionaries
可能会有任何帮助吗?不幸的是,我无法更改正在使用的数组的大小。
+++Function header+++
...
...
directoryPath=raw_input('Directory path for native csv file: ')
csvfile = numpy.genfromtxt(directoryPath, delimiter=",")
x=csvfile[:,2]
x1=numpy.delete(x, 0, 0)
x2=numpy.zeros((x1.shape[0]))
x2=sorted(x1)
x3=numpy.around(x2, decimals=3)
count=numpy.zeros(len(x3))
#Iterates over the x3 array to find the number of occurrences of each value
for i in range(len(x3)):
temp=x3[i]
for j in range(len(x3)):
if (temp<=x3[j]):
count[j]=count[j]+1
#Creates a 2D array with (value, occurrences)
x4=numpy.zeros((len(x3), 2))
for i in range(len(x3)):
x4[i,0]=x3[i]
x4[i,1]=numpy.around((count[i]/x1.shape[0]),decimals=3)
...
...
+++Function continues+++
你应该使用np.where
,然后计算得到的索引向量的长度:
indices = np.where(x3 <= value)
count = len(indices[0])
import numpy as np
import pandas as pd
from collections import Counter
import matplotlib.pyplot as plt
arr = np.random.randint(0, 100, (100000,1))
df = pd.DataFrame(arr)
cnt = Counter(df[0])
df_p = pd.DataFrame(cnt, index=['data'])
df_p.T.plot(kind='hist')
plt.show()
整个脚本为 (100,000x1)
数组执行 (~2s) 的时间非常短。我没有计时,但如果您提供执行您的脚本所花费的时间,我们可以进行比较。
我使用 collections
to count the number of occurrences, my experiences with it have always been great (timewise). I converted it into DataFrame
中的 [Counter][2]
进行绘图并使用 T
进行转置。
您的数据确实有点重复,但您可以尝试进一步优化它。事实上,它非常快。
编辑
使用 cumsum()
import numpy as np
import pandas as pd
from collections import Counter
import matplotlib.pyplot as plt
arr = np.random.randint(0, 100, (100000,1))
df = pd.DataFrame(arr)
cnt = Counter(df[0])
df_p = pd.DataFrame(cnt, index=['data']).T
df_p['cumu'] = df_p['data'].cumsum()
df_p['cumu'].plot(kind='line')
plt.show()
编辑 2
对于 scatter()
绘图,您必须明确指定 (x,y)。此外,调用 df_p['cumu']
将导致 Series
,而不是 DataFrame
。
要正确显示散点图,您需要以下内容:
import numpy as np
import pandas as pd
from collections import Counter
import matplotlib.pyplot as plt
arr = np.random.randint(0, 100, (100000,1))
df = pd.DataFrame(arr)
cnt = Counter(df[0])
df_p = pd.DataFrame(cnt, index=['data']).T
df_p['cumu'] = df_p['data'].cumsum()
df_p.plot(kind='scatter', x='data', y='cumu')
plt.show()
如果效率很重要,您可以使用 numpy 函数 bincount,它需要整数:
import numpy as np
a=np.random.rand(66049).reshape((66049,1)).round(3)
z=np.bincount(np.int32(1000*a[:,0]))
大约需要1ms。
此致。
# for counting a single value
mask = (my_np_array == value_to_count).astype('uint8')
# or a condition
mask = (my_np_array <= max_value).astype('uint8')
count = np.sum(mask)