如何在 histogram/dataset 中丢弃超过特定频率的数据?
How to drop data above a certain frequency in a histogram/dataset?
为了让事情更清楚,我不想从直方图中删除整个 bin,我只想删除一些数据,使其低于所需的频率。图中的线显示了我想要的最大频率
对于上下文,我有一个包含多个角度的数据集。就使用的数据而言,我的问题与此处提出的问题 非常相似,但与 link 中的问题不同,我不想删除数据,只是减少数据。
我可以直接从直方图中执行此操作,还是只需要删除数据集中的一些数据?
编辑(抱歉,我是这里编码和格式的新手):
这是我尝试过的解决方案
bns = 30
hist, bins = np.histogram(dataset['Steering'], bins= bns)
removeddata = []
spb = 700
for j in range(bns):
rdata = []
for i in range(len(dataset['Steering'])):
if dataset['Steering'][i] >= bins[j] and dataset['Steering'][i] <=
bins[j+1]:
rdata.append(i)
rdata = shuffle(rdata)
rdata = rdata[spb:]
removeddata.extend(rdata)
print('removed:', len(removeddata))
dataset.drop(dataset.index[removeddata], inplace = True)
print ('remaining:', len(dataset))
center = (bins[:-1] + bins[1:])*0.5
plt.bar(center,hist,width=0.05)
plt.show()
这是别人的解决方案,但似乎对他们有用。即使直接复制,它仍然会抛出错误。我得到的错误是“ValueError:系列的真值不明确。使用 a.empty、a.bool()、a.item()、a.any() 或 a.all()”,我试图将 'and' 更改为 & 并收到错误“TypeError:无法使用 dtyped [float64] 数组和类型 [bool] 的标量执行 'rand_'”。不确定这到底指的是什么,但指向带有 if 语句的行。检查了所有的数据类型,它们都是 float64 类型,所以不确定我的下一步
这个答案不会重新分类或重新居中数据,但我相信它通常可以实现您的要求。从您链接的 post 的所选答案中的示例开始,我编辑 hist
数组,以便原始输入数据不会像您指出的那样更改是您的首选解决方案:
import numpy as np
import matplotlib.pyplot as plt
fig, (ax1, ax2) = plt.subplots(1,2)
ax1.set_title("Some data")
ax2.set_title("Gated data < threshold")
np.random.seed(10)
data = np.random.randn(1000)
num_bins = 23
avg_samples_per_bin = 200
hist, bins = np.histogram(data, num_bins)
width = 0.7 * (bins[1] - bins[0])
center = (bins[:-1] + bins[1:]) * 0.5
ax1.bar(center, hist, align='center', width=width)
threshold = 80
gated = np.empty([len(hist)], dtype=np.int64)
for i in range(len(hist)):
if hist[i] > threshold:
gated[i] = threshold
else:
gated[i] = hist[i]
ax2.bar(center, gated, align="center", width=width)
plt.show()
这给出了
此解决方案考虑了明确的要求,即丢弃超过频率阈值的原始输入数据。我留下了我的另一个答案,因为它更简单和不同,可能对其他用户有用。
为了澄清,这个答案生成了一个新的一维数据数组,其中包含更少的元素,然后根据该新数据绘制直方图。在删除元素之前对数据进行混洗(如果输入数据已预先排序),以防止从每个 bin 的低侧或高侧丢弃数据时出现偏差。
import numpy as np
import matplotlib.pyplot as plt
from random import shuffle
def remove_gated_val_recursive(idx, to_gate_lst, bins_lst, data_lst):
if to_gate_lst[idx] == 0:
return(data_lst)
else:
bin_min, bin_max = bins_lst[idx], bins_lst[idx + 1]
for i in range(len(data_lst)):
if bin_min <= data_lst[i] < bin_max:
del data_lst[i]
to_gate_lst[idx] -= 1
break
return remove_gated_val_recursive(idx, to_gate_lst, bins_lst, data_lst)
threshold = 80
fig, ax1 = plt.subplots()
ax1.set_title("Some data")
np.random.seed(30)
data = np.random.randn(1000)
num_bins = 23
raw_hist, raw_bins = np.histogram(data, num_bins)
to_gate = []
for i in range(len(raw_hist)):
if raw_hist[i] > threshold:
to_gate.append(raw_hist[i] - threshold)
else:
to_gate.append(0)
data_lst = list(data)
shuffle(data_lst)
for idx in range(len(raw_hist)):
remove_gated_val_recursive(idx, to_gate, raw_bins, data_lst)
new_data = np.array(data_lst)
hist, bins = np.histogram(new_data, num_bins)
width = 0.7 * (bins[1] - bins[0])
center = (bins[:-1] + bins[1:]) * 0.5
ax1.bar(center, hist, align='center', width=width)
plt.show()
给出以下直方图,根据 new_data
数组绘制。
为了让事情更清楚,我不想从直方图中删除整个 bin,我只想删除一些数据,使其低于所需的频率。图中的线显示了我想要的最大频率
对于上下文,我有一个包含多个角度的数据集。就使用的数据而言,我的问题与此处提出的问题
我可以直接从直方图中执行此操作,还是只需要删除数据集中的一些数据?
编辑(抱歉,我是这里编码和格式的新手): 这是我尝试过的解决方案
bns = 30
hist, bins = np.histogram(dataset['Steering'], bins= bns)
removeddata = []
spb = 700
for j in range(bns):
rdata = []
for i in range(len(dataset['Steering'])):
if dataset['Steering'][i] >= bins[j] and dataset['Steering'][i] <=
bins[j+1]:
rdata.append(i)
rdata = shuffle(rdata)
rdata = rdata[spb:]
removeddata.extend(rdata)
print('removed:', len(removeddata))
dataset.drop(dataset.index[removeddata], inplace = True)
print ('remaining:', len(dataset))
center = (bins[:-1] + bins[1:])*0.5
plt.bar(center,hist,width=0.05)
plt.show()
这是别人的解决方案,但似乎对他们有用。即使直接复制,它仍然会抛出错误。我得到的错误是“ValueError:系列的真值不明确。使用 a.empty、a.bool()、a.item()、a.any() 或 a.all()”,我试图将 'and' 更改为 & 并收到错误“TypeError:无法使用 dtyped [float64] 数组和类型 [bool] 的标量执行 'rand_'”。不确定这到底指的是什么,但指向带有 if 语句的行。检查了所有的数据类型,它们都是 float64 类型,所以不确定我的下一步
这个答案不会重新分类或重新居中数据,但我相信它通常可以实现您的要求。从您链接的 post 的所选答案中的示例开始,我编辑 hist
数组,以便原始输入数据不会像您指出的那样更改是您的首选解决方案:
import numpy as np
import matplotlib.pyplot as plt
fig, (ax1, ax2) = plt.subplots(1,2)
ax1.set_title("Some data")
ax2.set_title("Gated data < threshold")
np.random.seed(10)
data = np.random.randn(1000)
num_bins = 23
avg_samples_per_bin = 200
hist, bins = np.histogram(data, num_bins)
width = 0.7 * (bins[1] - bins[0])
center = (bins[:-1] + bins[1:]) * 0.5
ax1.bar(center, hist, align='center', width=width)
threshold = 80
gated = np.empty([len(hist)], dtype=np.int64)
for i in range(len(hist)):
if hist[i] > threshold:
gated[i] = threshold
else:
gated[i] = hist[i]
ax2.bar(center, gated, align="center", width=width)
plt.show()
这给出了
此解决方案考虑了明确的要求,即丢弃超过频率阈值的原始输入数据。我留下了我的另一个答案,因为它更简单和不同,可能对其他用户有用。
为了澄清,这个答案生成了一个新的一维数据数组,其中包含更少的元素,然后根据该新数据绘制直方图。在删除元素之前对数据进行混洗(如果输入数据已预先排序),以防止从每个 bin 的低侧或高侧丢弃数据时出现偏差。
import numpy as np
import matplotlib.pyplot as plt
from random import shuffle
def remove_gated_val_recursive(idx, to_gate_lst, bins_lst, data_lst):
if to_gate_lst[idx] == 0:
return(data_lst)
else:
bin_min, bin_max = bins_lst[idx], bins_lst[idx + 1]
for i in range(len(data_lst)):
if bin_min <= data_lst[i] < bin_max:
del data_lst[i]
to_gate_lst[idx] -= 1
break
return remove_gated_val_recursive(idx, to_gate_lst, bins_lst, data_lst)
threshold = 80
fig, ax1 = plt.subplots()
ax1.set_title("Some data")
np.random.seed(30)
data = np.random.randn(1000)
num_bins = 23
raw_hist, raw_bins = np.histogram(data, num_bins)
to_gate = []
for i in range(len(raw_hist)):
if raw_hist[i] > threshold:
to_gate.append(raw_hist[i] - threshold)
else:
to_gate.append(0)
data_lst = list(data)
shuffle(data_lst)
for idx in range(len(raw_hist)):
remove_gated_val_recursive(idx, to_gate, raw_bins, data_lst)
new_data = np.array(data_lst)
hist, bins = np.histogram(new_data, num_bins)
width = 0.7 * (bins[1] - bins[0])
center = (bins[:-1] + bins[1:]) * 0.5
ax1.bar(center, hist, align='center', width=width)
plt.show()
给出以下直方图,根据 new_data
数组绘制。