“平均”分配项目的算法


25

我正在寻找一种算法来分配列表中的值,以使结果列表尽可能“平衡”或“均匀分布”(用引号引起来,因为我不确定这些是描述它的最佳方法...稍后,我将提供一种方法来衡量结果是否优于其他结果。

因此,对于列表:

[1, 1, 2, 2, 3, 3]

重新分配值之后,最好的结果之一是:

[1, 2, 3, 1, 2, 3]

可能还会有其他结果,但当然,使用一组不太统一的值会变得更加复杂。

这是衡量结果是否优于其他方法的方法:

  1. 计算每个项目和具有相同值的下一个项目之间的距离。

  2. 计算该组距离的标准偏差。较低的分散度意味着更好的结果。

观察结果:

  • 当计算距离并到达列表的末尾而没有找到具有相同值的项目时,我们返回到列表的开始。因此,最多将找到相同的项目,并且该项目的距离将是列表的长度。这意味着列表是循环的
  • 一个典型的列表有〜50个项目,其中〜15个不同值的数量不同。

所以:

  • 结果[1, 2, 3, 1, 2, 3]是距离为[3, 3, 3, 3, 3, 3],标准差为0;
  • 结果[1, 1, 2, 2, 3, 3]是距离为[1, 5, 1, 5, 1, 5],标准差为2;
  • 这使第一个结果优于第二个结果(偏差越小越好)。

给定这些定义,我想知道应该搜索哪些算法或策略的线索。


好像您想至少近似地解决分区问题(优化问题)。那个可能有很多算法!
拉斐尔

重新读一遍,为什么不计算所有值的出现然后循环放置值并不总是能产生最优解?
拉斐尔

Answers:


8

在研究类似问题时,我遇到了这个问题:最佳添加液体以减少分层。我的解决方案似乎也适用于您的情况。

如果要按30、20、10的比例(即A的30单位,B的20单位和C的10单位)混合液体A,B和C,则最终将全部添加A,然后是所有B,然后是所有C。您最好混合使用较小的单元。例如,按顺序[A,B,A,C,B,A]进行单单元加法。这将完全防止分层。

我发现这样做的方法是使用优先级队列将其视为一种合并。如果我创建一个结构来描述添加的内容:

MergeItem
    Item, Count, Frequency, Priority

频率表示为“每N个一个”。因此,六分之三的A的频率为2(6/3)。

并初始化最初包含的堆:

(A, 3, 2, 2)
(B, 2, 3, 3)
(C, 1, 6, 6)

现在,我从堆中删除第一项并将其输出。然后将其计数减少1,并按频率增加Priority,然后将其添加回堆中。产生的堆为:

(B, 2, 3, 0)
(A, 2, 2, 4)
(C, 1, 6, 6)

接下来,从堆中删除B,输出并更新它,然后重新添加到堆中:

(A, 2, 2, 4)
(C, 1, 6, 6)
(B, 1, 3, 6)

如果我以这种方式继续下去,我会得到想要的混合物。我使用一个自定义比较器来确保将相等的优先级项插入堆中时,首先对频率值最高(即频率最小)的项进行排序。

我在博客上写了关于此问题及其解决方案的更完整描述,并提供了一些说明该问题的有效C#代码。请参阅平均分配列表中的项目

评论后更新

我确实认为我的问题类似于OP的问题,因此我的解决方案可能很有用。抱歉,我对OP的问题不加框框。

第一个反对意见是,我的解决方案使用的是A,B和C,而不是0、1和2,这很容易解决。这只是一个命名问题。我发现思考和说“两个A”而不是“两个1”更容易,也不会造成混淆。但是出于讨论的目的,我在下面修改了我的输出以使用OP的术语。

当然,我的问题涉及距离的概念。如果您想“均匀地散布东西”,则意味着距离。但是,同样,这是我的失败,因为我没有充分展示我的问题与OP的问题有何相似之处。

我使用OP提供的两个示例进行了一些测试。那是:

[1,1,2,2,3,3]  // which I converted to [0,0,1,1,2,2]
[0,0,0,0,1,1,1,2,2,3]

在我的术语中,这些分别表示为[2,2,2]和[4,3,2,1]。也就是说,在最后一个示例中,“类型为0的4个项目,类型1的3个项目,类型2的2个项目和类型3的1个项目”。

我运行了测试程序(如下文所述),并发布了结果。缺少OP的输入,我不能说我的结果是否与他的相似,差或好。我也无法将我的结果与其他人的结果进行比较,因为其他人都没有发布任何结果。

但是我可以说,该算法为解决在混合液体时消除分层的问题提供了一个很好的解决方案。它看起来像它提供了一个合理的解决OP的问题。

对于下面显示的结果,我使用了我在博客条目中详细介绍的算法,将初始优先级设置为Frequency/2,并修改了堆比较器以支持更频繁的项目。此处显示了修改后的代码,并注释了修改后的行。

private class HeapItem : IComparable<HeapItem>
{
    public int ItemIndex { get; private set; }
    public int Count { get; set; }
    public double Frequency { get; private set; }
    public double Priority { get; set; }

    public HeapItem(int itemIndex, int count, int totalItems)
    {
        ItemIndex = itemIndex;
        Count = count;
        Frequency = (double)totalItems / Count;
        // ** Modified the initial priority setting.
        Priority = Frequency/2;
    }

    public int CompareTo(HeapItem other)
    {
        if (other == null) return 1;
        var rslt = Priority.CompareTo(other.Priority);
        if (rslt == 0)
        {
            // ** Modified to favor the more frequent item.
            rslt = Frequency.CompareTo(other.Frequency);
        }
        return rslt;
    }
}

使用OP的第一个示例运行测试程序,我得到:

Counts: 2,2,2
Sequence: 1,0,2,1,0,2
Distances for item type 0: 3,3
Stddev = 0
Distances for item type 1: 3,3
Stddev = 0
Distances for item type 2: 3,3
Stddev = 0

因此,我的算法适用于所有数量相等的琐碎问题。

对于OP发布的第二个问题,我得到了:

Counts: 4,3,2,1
Sequence: 0,1,2,0,1,3,0,2,1,0
Distances for item type 0: 3,3,3,1
Stddev = 0.866025403784439
Distances for item type 1: 3,4,3
Stddev = 0.471404520791032
Distances for item type 2: 5,5
Stddev = 0
Distances for item type 3: 10
Stddev = 0
Standard dev: 0.866025403784439,0.471404520791032,0,0

我看不出有明显的改进方法。可以重新排列它以使项目0 [2,3,2,3]的距离或其他一些项目2和3的距离,但这将更改项目1和/或2的偏差。我真的不知道在这种情况下“最佳”。在频率较高或频率较低的项目上偏差较大是否更好?

缺少OP中的其他问题,我用他的描述构成了一些我自己的描述。他在帖子中说:

一个典型的列表有〜50个项目,其中〜15个不同值的数量不同。

所以我的两个测试是:

[8,7,6,5,5,4,3,3,2,2,2,1,1,1,1]  // 51 items, 15 types
[12,6,5,4,4,3,3,3,2,2,2,1,1]     // 48 items, 13 types

我的结果是:

Counts: 8,7,6,5,5,4,3,3,2,2,2,1,1,1,1
Sequence: 0,1,2,3,4,5,7,6,0,1,2,8,9,10,4,3,0,1,5,2,0,1,3,4,6,7,14,11,13,12,0,2,5,1,0,3,4,2,8,10,9,1,0,7,6,5,3,4,2,1,0
Distances for item type 0: 8,8,4,10,4,8,8,1
Stddev = 2.82566363886433
Distances for item type 1: 8,8,4,12,8,8,3
Stddev = 2.76272565797339
Distances for item type 2: 8,9,12,6,11,5
Stddev = 2.5
Distances for item type 3: 12,7,13,11,8
Stddev = 2.31516738055804
Distances for item type 4: 10,9,13,11,8
Stddev = 1.72046505340853
Distances for item type 5: 13,14,13,11
Stddev = 1.08972473588517
Distances for item type 6: 17,20,14
Stddev = 2.44948974278318
Distances for item type 7: 19,18,14
Stddev = 2.16024689946929
Distances for item type 8: 27,24
Stddev = 1.5
Distances for item type 9: 28,23
Stddev = 2.5
Distances for item type 10: 26,25
Stddev = 0.5
Distances for item type 11: 51
Stddev = 0
Distances for item type 12: 51
Stddev = 0
Distances for item type 13: 51
Stddev = 0
Distances for item type 14: 51
Stddev = 0

对于第二个示例:

Counts: 12,6,5,4,4,3,3,3,2,2,2,1,1
Sequence: 0,1,2,0,3,4,7,5,6,0,1,8,9,10,0,2,0,3,4,1,0,2,6,7,5,12,11,0,1,0,3,4,2,0,1,10,8,9,0,7,5,6,0,
4,3,2,1,0
Distances for item type 0: 3,6,5,2,4,7,2,4,5,4,5,1
Stddev = 1.68325082306035
Distances for item type 1: 9,9,9,6,12,3
Stddev = 2.82842712474619
Distances for item type 2: 13,6,11,13,5
Stddev = 3.44093010681705
Distances for item type 3: 13,13,14,8
Stddev = 2.34520787991171
Distances for item type 4: 13,13,12,10
Stddev = 1.22474487139159
Distances for item type 5: 17,16,15
Stddev = 0.816496580927726
Distances for item type 6: 14,19,15
Stddev = 2.16024689946929
Distances for item type 7: 17,16,15
Stddev = 0.816496580927726
Distances for item type 8: 25,23
Stddev = 1
Distances for item type 9: 25,23
Stddev = 1
Distances for item type 10: 22,26
Stddev = 2
Distances for item type 11: 48
Stddev = 0
Distances for item type 12: 48
Stddev = 0

@DW请参阅我的更新。我相信我可以证明我的问题与OP的问题如何相似,以及我的算法如何为OP的问题提供解决方案。
Jim Mischel

好东西!感谢您的出色更新。已投票。
DW

正如我之前说过的,这很有趣。这个想法的简单性很吸引人。我没有时间仔细阅读所有内容。您的解决方案实际上考虑了原始问题的周期性吗?可能有一种方法可以针对此目的进行调整,但是我不确定,它是否可以正常工作。
2015年

@babou:正如您在结果中看到的那样,我的距离计算确实可以回绕,但是算法本身并没有为OP问题的周期性提供任何具体的余地。我也看不出有什么方法可以使算法适应这一要求。或者,就此而言,如何考虑周期性会改善结果。尽管考虑将所有计数加倍(即将[3,2,1]更改为[6,4,2])很有趣,但这实际上是同一件事。我怀疑该算法会产生相同的结果。
Jim Mischel

6

这种“闻起来”就像是对NP不利的。那么,当您遇到NP难题时,您该怎么办?对其进行启发式或近似算法,或使用SAT求解器。

在您的情况下,如果您不需要绝对最佳解,那么一个合理的起点可能是尝试模拟退火。有一种自然的方法来获取任何候选解决方案并将其移至附近的候选解决方案:随机选择列表中的两个项目,然后交换它们。模拟退火将迭代地尝试改善解决方案。如果您不熟悉模拟退火,可以找到很多资源。您还可以尝试对候选解决方案进行细微更改的其他“局部移动”集,以期逐步改进它(即减少距离的标准偏差)。

ttt2xi,jxi,jijt2

但是我建议您从模拟退火开始。这是我要尝试的第一件事,因为我认为它可能会起作用。


您的建议是解决这类调度问题的标准方法吗?我猜这周围有一些商业软件。他们如何处理?
2014年

@babou,好问题-我不知道!
DW

我进一步开发了算法的细节,但是我怀疑很多现有的应用程序会使用它。实际上,我什至不知道调度应用程序是否可以解决此类问题。我一直在询问有关SE.softwarerecs的信息,因为除了我刚才的评论之外,我在这里看不到如何提出问题。
2014年

最佳解决方案可能是NP难。但是一个可行的解决方案是O(n log k),其中n是项目总数,k是项目类型数。查看我的答案和链接的博客文章。
Jim Mischel

2

启发式算法的草图

对于此问题,我没有确切的解决方案。但是由于拉斐尔(Raphael)的评论表明它看起来像分区问题(针对启发式算法已针对该问题开发了这种方法),因此我将尝试一种启发式方法。这只是启发式算法的草图。

vn[1..n]ini

nvnvn/nv

v

in/ninmodnin/ni

这将指导我们的算法。

n

i|n/niv|

起初它可能是一个出现很少的值。我认为这实际上没有什么区别,因为占用槽位所产生的约束与放置的值(?)的数量成比例。

所考虑的第一个值可以不受任何限制地放置。然后,必须放置其他值,以最小化它们对标准偏差的影响,但只能放置在之前放置了任何值的空闲插槽中。

可以使用动态编程算法来完成剩余时隙中值的出现的放置,以便合并在两个位置之间放置相同数量值的计算,仅保留那些对标准偏差贡献最小的计算(即偏差平方和的最小值)。

v

j|n/njv|

然后,将单例值放入剩余的插槽中。

我认为这通常可以提供合理的解决方案,但是我还不知道如何证明它或使用最佳解决方案估算差距。


我有一个相同的印象,那就是我们从最常见或最不常见的那些开始,将单身者放在一边都没关系。显然能给我最好结果的策略是开始按出现顺序对值进行排序,并从出现次数最多的位置开始将它们按顺序排列。这自然使单例结束。
moraes 2014年

vn/vV

您的意思是,对于具有10个值[0, 0, 0, 0, 1, 1, 1, 2, 2, 3]和v 的列表4,我们将放置第一个值110/3 = 3.33,最接近v),然后放置210/2 = 5,下一个最接近),然后放置010/4 = 2.5)?或者:您能否举一个“减少距离v的平均距离偏差”的示例?
moraes 2014年

1
不,我正相反。以您的示例为例,定位的顺序是第一个O,因为它的平均距离2,5与v = 4的偏差最大,然后是2,然后是1,然后是单例3。-是-是ypu建议我应该更清楚地重写一些内容我对此策略的解释的一部分?
2014年

不,还好。我会尝试一些与这个想法有关的事情并进行报告。
moraes 2014年

1

看来我参加聚会很晚了,但是要发贴,以防有人再次碰到。我的解决方案类似于@babou的plus。今天早些时候,我在嵌入式系统中遇到了调度问题,这导致我进入了该线程。我有一个针对我C语言问题的实现,但是我想我会在这里发布一个更通用的Python解决方案(由于我将自己限制在一个固定大小的小型堆栈且没有内存,因此C版本很复杂分配,因此我就地执行了整个算法)。下面使用的抗锯齿技术是您可以在2位色的屏幕上画线的一种方法。在使用Jim Mischel所使用的输入的标准偏差之和进行测量时,与该特定解决方案相比,此处的算法得分较低(即更好)。

def generate(item_counts):
'''item_counts is a list of counts of "types" of items. E.g., [3, 1, 0, 2] represents
   a list containing [1, 1, 1, 2, 4, 4] (3 types of items/distinct values). Generate
   a new list with evenly spaced values.'''
# Sort number of occurrences by decreasing value.
item_counts.sort(reverse=True)
# Count the total elements in the final list.
unplaced = sum(item_counts)
# Create the final list.
placements = [None] * unplaced

# For each type of item, place it into the list item_count times.
for item_type, item_count in enumerate(item_counts):
    # The number of times the item has already been placed
    instance = 0
    # Evenly divide the item amongst the remaining unused spaces, starting with
    # the first unused space encountered.
    # blank_count is the number of unused spaces seen so far and is reset for each
    # item type.
    blank_count = -1
    for position in range(len(placements)):
        if placements[position] is None:
            blank_count += 1
            # Use an anti-aliasing technique to prevent bunching of values.
            if blank_count * item_count // unplaced == instance:
                placements[position] = item_type
                instance += 1
    # Update the count of number of unplaced items.
    unplaced -= item_count

return placements

结果

Input counts: 8,7,6,5,5,4,3,3,2,2,2,1,1,1,1
Sum of stddev: 16.8 (vs. 22.3 via Jim Mischel)

Input of counts: 12,6,5,4,4,3,3,3,2,2,2,1,1
Sum of stddev: 18.0 (vs. 19.3 via Jim Mischel)

如果给定输入形式为@moraes指定的形式,则可以使用内存的Big Omega(n * log(n))位以O(n)步长将其转换为此函数可使用的形式,其中n是项数(在包含255个元素的列表中,通过保留具有重复计数的并行数组,您将不需要超过255个额外字节。或者,可以使用O(1)额外的内存执行一对就地排序。

聚苯乙烯

import numpy
import collections

def evaluate(l):
    '''Given a distribution solution, print the sum of stddevs for each type in the solution.'''
    l2 = l * 2
    distances = [None] * len(l)
    distance_dict = collections.defaultdict(list)
    for i in range(len(l)):
        distances[i] = l2.index(l[i], i + 1) - i
        distance_dict[l[i]].append(l2.index(l[i], i + 1) - i)

    keys = list(distance_dict.keys())
    keys.sort()
    score = 0
    # Calculate standard deviations for individual types.
    for key in keys:
        sc = numpy.std(distance_dict[key])
        score += sc
    print('Stddev sum: ', score)

编辑:我知道此解决方案无法通过反例产生最佳输出。的输入[6, 2, 1]产生[0, 1, 0, 0, 2, 0, 0, 1, 0]; 更好的解决方案是[0, 0, 1, 0, 2, 0, 0, 1, 0]


我相信我在代码注释中解释了我的算法,并在序言中解释了该算法的基础。
隆吉

我希望看到对您的算法背后的思想有完整的描述,并为该算法提供简洁的伪代码。目前,我在介绍性文本中看到的是(1)您的方法类似于@babou的方法,并且(2)它使用了抗锯齿技术(以某种方式)。另外,并不是每个人都阅读Python。无论如何,这都是一个古老的答案,所以我了解您是否不想对其进行改进,但我只是注意到我们对本网站的期望-不仅是对您的期望,也是对可能在此页面上运行的其他人的期望未来并倾向于回答。
DW

0

此算法适用于整数数组,其中每个整数代表不同的类别。它为每个类别创建单独的数组。例如,如果起始数组为[1、1、1、2、2、3],它将创建三个数组,[3],[2、2],[1、1、1]。

从那里它递归地合并两个最小的数组(在本例中为[3]和[2,2]),并将较小数组的元素的位置主要根据数量的比率分配到第二个最小数组中较大类别和较小类别的出现次数的比例。在此示例中,我们将得出[2,3,2]。然后,它将使用该数组作为较小的数组,将其合并到下一个较大的数组中,直到仅剩一个数组为止。

<?php
/**
 *This will separete the source array into separate arrays for each category
 */
function splitArrayByCategory($source) {

    //  index is the category, value is the tally
    $categoryCounts  = array_count_values($source);

    // Sort that list, keep index associations
    asort($categoryCounts);

    // build separate arrays for each category
    // index = order, smaller index = smaller category count
    // value = array of each category
    $separated = array();
    foreach ($categoryCounts as $category => $tally)
        $separated[] = array_fill(0, $tally, $category);

    return $separated;
}

/**
 * Will take the array of arrays generated by splitArrayByCategory, and merge
 * them together so categories are evenly distributed
 */
function mergeCategoryArrays($categoryArray) {

    // How many entries are there, for the smallest & second smallest categories
    $smallerCount = count($categoryArray[0]);
    $largerCount  = count($categoryArray[1]);

    // Used to determine how much space there should be between these two categories
    $space = $largerCount/$smallerCount;

    // Merge the array of the smallest category into the array of the second smallest
    foreach ($categoryArray[0] as $domIndex => $domain) {
        // Where should we splice the value into the second array?
        $location = floor($domIndex*$space+$domIndex+($space/2));
        // actually perform the splice
        array_splice($categoryArray[1], $location, 0, $domain);
    }

    // remove the smallest domain we just spliced into the second smallest
    unset($categoryArray[0]);

    // reset the indexes
    $categoryArray = array_values($categoryArray);

    // If we have more than one index left in the categoryArray (i.e. some things
    // still need to get merged), let's re-run this function,
    if (count($categoryArray)>1)
        $categoryArray = mergeCategoryArrays($categoryArray);

    return $categoryArray;
}

// The sample list we're working with.
// each integer represents a different category
$listSample = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,6,6,7,7,7,7];

// Split the sample list into separate arrays for each category
$listSplitByCategory = splitArrayByCategory($listSample);

// If there are not at least two categories, what's the point?
if (count($listSplitByCategory) < 2) throw new Exception("You need at least two categories");

// perform the actual distribution of categories.
$listEvenlyDistributed = mergeCategoryArrays($listSplitByCategory)[0];

// Display the array before and after the categories are evenly distributed
for ($i=0; $i<count($listSample); $i++) {
    print $listSample[$i].",";
    print $listEvenlyDistributed[$i]."\n";
}

2
这不是一个编码站点。请不要发布仅代码的答案。相反,我们希望您解释答案背后的想法,并为您的算法提供简洁的伪代码。
DW

欢迎来到计算机科学!万一您不知道或暂时忘了,以某种特定语言阅读代码通常是我们可以完成的最艰巨的任务之一,即使有时代码是我们自己编写的。这就是为什么我们对此站点不太欣赏真实代码的部分原因,尽管它可能比松散编写的伪代码代表更多的工作。当然,我确实感谢所有可以立即运行或闪烁的实际工作代码。
Apass.Jack

在那里有解释。在注释的演示代码中;它不是采用某些过时的语法(例如APL),而是一种易于理解的语法,与伪代码非常接近。如果我的解释不是用等宽字体会有所帮助吗?
vtim

是。确实有帮助。并非每个人都阅读PHP,也许不是每个人都可以确定注释是什么(也许是稻草人的论点),或者只是不想阅读代码块并对其进行解释,而是阅读了包含在顶部和底部的想法。它说明了一切。向我+1。您的代码干净整洁,但文件记录完整,但我们根本不是编写站点,因此此处的文本描述很重要。感谢您的修改。
邪恶的

-1

ANSI C代码

该代码通过想象n维空间(其中n是类别数)中的一条直线通过原点的方向向量(v1,v2,...,vi,... vn)来工作,其中vi是类别i中的项目。从原点开始,目标是找到直线的下一个最近点。使用示例[0 0 0 0 0 1 1 1 2 2 2 3]产生结果[0 1 2 0 3 1 0 2 0 1 2 0]。使用Lungj的示例[0 0 0 0 0 0 1 1 2],我们得到[0 1 0 0 2 0 0 1 0],这与Lungj的结果完全相同。

仅使用整数算法并仅考虑从每个点到线的距离之间的增量,可以使该算法更有效。

#define MAXCATEGORIES 100

int main(){int i = 0; int j = 0; int catsize = 0; int vector [MAXCATEGORIES]; 积分点[MAXCATEGORIES];int Categories = 0; int totalitems = 0; int best = 0; 长d2 = 0L; 长vp = 0L; 长v2 = 0L;长增量= 0L; 长Beta = 0L;

printf("Enter the size of each category (enter 0 to finish):\r\n");
do
{
    catsize = 0;
    #ifdef _MSVC_LANG
            scanf_s("%d", &catsize);
    #else
            scanf("%d", &catsize)
    #endif
    if (catsize > 0)
    {
        vector[categories] = catsize;
        totalitems += catsize;
        categories++;
    }
} while (catsize > 0);

for (i = 0; i < categories; i++)
{
    v2 += vector[i] * vector[i];
    point[i] = 0;
}

for (i = 0; i < totalitems; i++)
{
    for (j = 0; j < categories; j++)
    {
        delta = (2 * point[j] + 1)*v2 - (2 * vp + vector[j])*vector[j];
        if (j == 0 || delta < beta)
        {
            best = j;
            beta = delta;
        }
    }
    point[best]++;
    vp += vector[best];
    printf("%c ", best + '0');  // Change '0' to 'A' if you like letters instead
}
return 0;

}


1
欢迎光临本站!在格式化方面,您需要在代码的每一行缩进四个空格,以便系统正确地进行标记。通常,我们不是在寻找大的代码块作为问题的答案,尤其是,您的数据输入例程在此处未添加任何内容。您在文章的顶部有一些解释,但是最好对此加以扩展并减少代码。
David Richerby

这不是一个编码站点。请不要发布仅代码的答案。相反,我们希望您解释答案背后的想法,并为您的算法提供简洁的伪代码。
DW

-1

我的解决方案:

    vc = train['classes'].value_counts()
    vc = dict(sorted(vc.items()))
    df = pd.DataFrame()
    train['col_for_sort'] = 0.0

    i=1
    for k,v in vc.items():
        step = train.shape[0]/v
        indent = train.shape[0]/(v+1)
        df2 = train[train['classes'] == k].reset_index(drop=True)
        for j in range(0, v):
        df2.at[j, 'col_for_sort'] = indent + j*step + 0.0001*i   
    df= pd.concat([df2,df])
    i+=1

    train = df.sort_values('col_for_sort', ascending=False).reset_index(drop=True)
    del train['col_for_sort']

请使用伪代码(带有一些必要的注释)来描述您的算法。
xskxzr

这不是一个编码站点。请不要发布仅代码的答案。相反,我们希望您解释答案背后的想法,并为您的算法提供简洁的伪代码。
DW
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.