Python 捕获非整列车中的所有数据,测试和验证拆分

Python 捕获非整列车中的所有数据,测试和验证拆分,python,split,sampling,training-data,Python,Split,Sampling,Training Data,我只是想知道是否有更好的办法来解决这类问题 我们知道,对于偶数的X/Y百分比分割,我们可以得到数据的精确分割-例如,对于数据大小10: 10 * .6 = 6 10 * .4 = 4 10 以这种方式分割数据很容易,而且我们可以保证我们拥有所有数据,并且不会丢失任何数据。然而,我所挣扎的是不太友好的数字——以11为例 11 * .6 = 6.6 11 * .4 = 4.4 11 但是,例如,我们不能索引到i=6.6的数组中。因此,我们必须决定如何做到

我只是想知道是否有更好的办法来解决这类问题

我们知道,对于偶数的X/Y百分比分割,我们可以得到数据的精确分割-例如,对于数据大小10:

10 * .6 = 6
10 * .4 = 4
          10 
以这种方式分割数据很容易,而且我们可以保证我们拥有所有数据,并且不会丢失任何数据。然而,我所挣扎的是不太友好的数字——以11为例

11 * .6 = 6.6
11 * .4 = 4.4
          11
但是,例如,我们不能索引到
i=6.6
的数组中。因此,我们必须决定如何做到这一点。如果只取整数部分,则会丢失1个数据点-

First set = 0..6
Second set = 6..10
如果我们把数字搞清楚,情况也会一样

但是,如果我们采用数字上限:

First set = 0..7
Second set = 7..12
我们已经读过了数组的末尾

当我们进行第三次或第四次分割时(例如30,30,20,20),情况会变得更糟

这类问题是否有标准的拆分程序?是否接受数据丢失?对于依赖数据(如时间序列),数据丢失似乎是不可接受的

谢谢


编辑:
.6
.4
由我选择。它们可以是总和为
1

的任意两个数字,而不是使用
ciel()
floor()
来代替。例如:

>>> round(6.6)
7.0
返回的值将是
float
类型。要获取整数值,请将其强制转换为
int
as:

>>> int(round(6.6))
7
这将是您第一次拆分的值。要获得第二次拆分,请使用
len(data)-split1\u val
计算它。这将适用于2分裂问题的情况


如果是三次拆分,则取两次拆分的四舍五入值,并将第三次拆分的值作为
len(我的列表)-val\u split\u 1-val\u split2的值

一般来说,对于N个拆分

N-1
split的
round()
值。对于最后一个值,请执行len(数据)
-“N个round()值的值”


其中
len()
给出了列表的长度

首先,请注意,您的问题不限于您声称的奇数大小的阵列,而是任何大小的阵列。如何对10个元素的数组进行56%-44%的拆分?还是4元素数组的60%-40%分割

没有标准的程序。在许多情况下,程序员并不太关心精确的分割,他们要么通过对一个数量(第一组的大小)进行加铺或四舍五入来实现,而对另一个数量(第二组的大小)采用互补的(数组长度-四舍五入的大小)

在大多数情况下,当这是一次性计算且不需要精确性时,这可能是可行的你必须问问自己你的要求是什么。例如:您是否正在使用数千个10大小的数组,每次将它们拆分为56%-44%,然后进行一些计算并返回结果?你必须问问自己你想要什么样的准确度。你在乎你的结果最终会不会被忽略吗 60%-40%的分割还是50%-50%的分割

再举一个例子,假设你在做一个25%-25%-25%-25%的四向等分。如果有10个元素,并应用舍入技术,则最终得到3,3,3,1个元素。这肯定会把你的结果搞砸

如果你关心所有这些不准确,那么第一步是考虑你是否可以调整数组大小和/或分裂比率(s)。p> 如果这些都是一成不变的,那么对任何大小的数组的任何比率进行精确分割的唯一方法是使其具有概率性。您必须拆分多个阵列才能工作(这意味着您必须多次对相同大小的阵列应用相同的拆分比率)。数组越多越好(或者可以多次使用同一个数组)

因此,假设您必须对10个大小的阵列进行56%-44%的拆分。这意味着您需要将其平均分为5.6个元素和4.4个元素

有很多方法可以达到5.6个元素的平均值。最简单的方法(也是在一系列尝试中方差最小的方法)是在一个包含6个元素的集合中有60%的时间,在一个包含5个元素的集合中有40%的时间

0.6*6+0.4*5=5.6

就代码而言,您可以这样做来决定每次集合的大小:

import random

array_size = 10
first_split = 0.56
avg_split_size = array_size * first_split 
floored_split_size = int(avg_split_size)

if avg_split_size > floored_split_size:
    if random.uniform(0,1) > avg_split_size - floored_split_size:
        this_split_size = floored_split_size
    else: 
        this_split_size = floored_split_size + 1    
else:
    this_split_size = avg_split_size

你可以让代码更简洁,我只是在这里做了一个提纲,这样你就明白了。我希望这有帮助 假设
n
是我们要拆分的元素数,
p
q
是比例,以便

p+q==1

我断言小数点后的部分总和总是
1
0
因此我们应该在一个上使用
floor
,在另一个上使用
ceil
,我们永远是对的

这里有一个函数可以实现这一点,还有一个测试。我留下了打印语句,但它们被注释掉了

def simpleSplitN(n, p, q):
    "split n into proportions p and q and return indices"
    np = math.ceil(n*p)
    nq = math.floor(n*q)
    #print n, sum([np, nq]) #np and nq are the proportions
    return [0, np] #these are the indices we would use

#test for simpleSplitN
for i in range(1, 10):
    p = i/10.0;
    q = 1-p
    simpleSplitN(37, p, q);
对于有数学倾向的人,这里有一个证据,证明小数比例之和为
1

--------------------------

我们可以将
p*n
表示为
n/(1/p)
,因此通过除法算法我们得到整数
k
r


n==k*(1/p)+r
with
0@anonymous在两次拆分的情况下,是的,您可以将剩余部分作为第二组。如果我们有3次拆分,你就不能这么简单了。如果是3次拆分,取两次拆分的四舍五入值,取第3次拆分的值作为len(我的列表)-val_split_1-val_split2的值,其中len()给出了列表的长度。加上答案,取n=15;那么.7*15=10.5,.3*15=4.5;但是四舍五入(10.5)+四舍五入(4.5)=11+5=16似乎您需要一个特例,如果四舍五入结束,只需使用数据大小
import math
import random

def splitN(n, c):
    """Compute indices that can be used to split
    a dataset of n items into a list of proportions c
    by first dividing them naively and then distributing
    the decimal parts of said division randomly
    """
    nc = [n*i for i in c];
    nr = [n*i - int(n*i) for i in c] #the decimal parts
    N = int(round(sum(nr)))          #sum of all decimal parts
    print N, nc
    for i in range(0, len(nc)):
        nc[i] = math.floor(nc[i])
    for i in range(N):                  #randomly distribute leftovers
        nc[random.randint(1, len(nc)) - 1] += 1
    print n,sum(nc);                    #nc now contains the proportions
    out = [0]                           #compute a cumulative sum
    for i in range(0, len(nc) - 1):
        out.append(out[-1] + nc[i])
    print out
    return out

#test for splitN with various proportions
c = [.1,.2,.3,.4]
c = [.2,.2,.2,.2,.2]
c = [.3, .2, .2, .3]
for n in range( 10, 40 ):
    print splitN(n, c)