Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 从dataframe生成多个分类变量之间具有偶数表示的列表_Python_List_Pandas_Unique_Itertools - Fatal编程技术网

Python 从dataframe生成多个分类变量之间具有偶数表示的列表

Python 从dataframe生成多个分类变量之间具有偶数表示的列表,python,list,pandas,unique,itertools,Python,List,Pandas,Unique,Itertools,我试图从DF中定义组。根据分类变量,这些组必须尽可能相似 例如,我有10个弹珠,需要分成3组。我的弹珠有4颗是蓝色的,2颗是黄色的,4颗是白色的 10颗大理石不会平均分为3组,因此组大小将为4,3,3,即尽可能接近均匀 同样,由于我们只有2个黄色,所以颜色在组之间不会有均匀的表示。然而,这些黄色大理石必须尽可能均匀地分布在各个群体中。这将在数据集中的所有分类变量中继续 我最初的计划是检查该行是否存在于其他组中,如果在一个组中,请尝试另一个组。我的同事指出了一种更好的生成组的方法,用一个热编码对组

我试图从DF中定义组。根据分类变量,这些组必须尽可能相似

例如,我有10个弹珠,需要分成3组。我的弹珠有4颗是蓝色的,2颗是黄色的,4颗是白色的

10颗大理石不会平均分为3组,因此组大小将为4,3,3,即尽可能接近均匀

同样,由于我们只有2个黄色,所以颜色在组之间不会有均匀的表示。然而,这些黄色大理石必须尽可能均匀地分布在各个群体中。这将在数据集中的所有分类变量中继续

我最初的计划是检查该行是否存在于其他组中,如果在一个组中,请尝试另一个组。我的同事指出了一种更好的生成组的方法,用一个热编码对组进行评分,然后交换行,直到一个热编码的总和接近相似的水平(表明行中包含每个组中分类变量的“接近代表性”变化)。他的解决方案是发布答案

import pandas as pd
import numpy as np
test = pd.DataFrame({'A' : ['alice', 'bob', 'george', 'michael', 'john', 'peter', 'paul', 'mary'], 
                 'B' : ['one', 'one', 'two', 'three', 'two', 'two', 'one', 'three'],
                 'C' : ['dog', 'cat', 'dog', 'cat', 'dog', 'cat', 'dog', 'cat'],
                 'D' : ['boy', 'girl', 'boy', 'girl', 'boy', 'girl', 'boy', 'girl']})
gr1, gr2, gr3 = [], [], []
gr1_names = []
def test_check1(x):

    #this is where I'm clearly not approaching this problem correctly
    for index, row in x.iterrows():
        if row['A'] not in gr1 and row['B'] not in gr1 and row['C'] not in gr1 and row['D'] not in gr1:
                 gr1.extend(row) # keep a record of what names are in what groups
                 gr1_names.append(row['A']) #save the name 
但是,就在这里,我还需要能够说“如果这一行不允许进入任何组,就把它扔进第一个组。然后,下一次这一行不允许进入任何组,就把它扔进第二个组”等等

我可以看出,我的示例代码不能充分处理这种情况

我尝试了一个随机数发生器,然后制作了垃圾箱,老实说,这非常接近,但我希望找到一个非随机的答案

以下是一些我认为对我今天的工作有帮助的链接:

---这一个感觉非常接近,但我不知道如何操纵它到我需要的---

预期输出将是任何形状的数据帧,但所述数据帧的枢轴将指示:

group id    foo bar faz
       1    3   2   5
       2    3   2   5
       3    3   1   5
       4    4   1   5

我的同事找到了一个解决方案,我认为这个解决方案更好地解释了这个问题

import pandas as pd
import random
import math
import itertools

def n_per_group(n, n_groups):
    """find the size of each group when splitting n people into n_groups"""
    n_per_group = math.floor(n/n_groups)
    rem = n % n_per_group
    return [n_per_group if k<rem else n_per_group + 1 for k in range(n_groups)]

def assign_groups(n, n_groups):
    """split the n people in n_groups pretty evenly, and randomize"""
    n_per = n_per_group(n ,n_groups)
    groups = list(itertools.chain(*[i[0]*[i[1]] for i in zip(n_per,list(range(n_groups)))]))
    random.shuffle(groups)
    return groups

def group_diff(df, g1, g2):
    """calculate the between group score difference"""
    a = df.loc[df['group']==g1, ~df.columns.isin(('A','group'))].sum()
    b = df.loc[df['group']==g2, ~df.columns.isin(('A','group'))].sum()
    #print(a)
    return abs(a-b).sum()

def swap_groups(df, row1, row2):
    """swap the groups of the people in row1 and row2"""
    r1group = df.loc[row1,'group']
    r2group = df.loc[row2,'group']
    df.loc[row2,'group'] = r1group
    df.loc[row1,'group'] = r2group
    return df

def row_to_group(df, row):
    """get the group associated to a given row"""
    return df.loc[row,'group']

def swap_and_score(df, row1, row2):
    """
    given two rows, calculate the between group scores
    originally, and if we swap rows. If the score difference
    is minimized by swapping, return the swapped df, otherwise
    return the orignal (swap back)
    """
    #orig = df
    g1 = row_to_group(df,row1)
    g2 = row_to_group(df,row2)
    s1 = group_diff(df,g1,g2)
    df = swap_groups(df, row1, row2)
    s2 = group_diff(df,g1,g2)
    #print(s1,s2)
    if s1>s2:
        #print('swap')
        return df
    else:
        return swap_groups(df, row1, row2)

def pairwise_scores(df):
    d = []
    for i in range(n_groups):
        for j in range(i+1,n_groups):
            d.append(group_diff(df,i,j))
    return d

# one hot encode and copy
df_dum = pd.get_dummies(df, columns=['B', 'C', 'D']).copy(deep=True)

#drop extra cols as needed

groups = assign_groups(n, n_groups)
df_dum['group'] = groups

# iterate
for _ in range(5000):
    rows = random.choices(list(range(n)),k=2)
    #print(rows)
    df_dum = swap_and_score(df_dum,rows[0],rows[1])
    #print(pairwise_scores(df))

print(pairwise_scores(df_dum))

df['group'] = df_dum.group
df['orig_groups'] = groups

for i in range(n_groups):
        for j in range(i+1,n_groups):
            a = df_dum.loc[df_dum['group']==3, ~df_dum.columns.isin(('A','group'))].sum()
            b = df_dum.loc[df_dum['group']==0, ~df_dum.columns.isin(('A','group'))].sum()
            print(a-b)
将熊猫作为pd导入
随机输入
输入数学
进口itertools
每个组定义n个(n,n个组):
“”“将n个人分成n个组时查找每个组的大小”“”
每组n\u=数学楼层(n/n\u组)
rem=每组n%n
如果ks2:
#打印(‘交换’)
返回df
其他:
返回交换组(df,第1行,第2行)
def成对_分数(df):
d=[]
对于范围内的i(n_组):
对于范围内的j(i+1,n_组):
d、 附加(组_diff(df,i,j))
返回d
#一个热编码和复制
df_dum=pd.get_dummies(df,columns=['B','C','D'])。copy(deep=True)
#如有需要,多放些可乐
组=分配组(n,n组)
df_dum['group']=组
#迭代
对于范围内的(5000):
行=随机。选择(列表(范围(n)),k=2)
#打印(行)
df_dum=交换_和_分数(df_dum,第[0]行,第[1]行)
#打印(成对分数(df))
打印(成对分数(df_dum))
df['group']=df_dum.group
df['orig_groups']=组
对于范围内的i(n_组):
对于范围内的j(i+1,n_组):
a=df_dum.loc[df_dum['group']==3,~df_dum.columns.isin(('a','group'))].sum()
b=df_dum.loc[df_dum['group']==0,~df_dum.columns.isin(('A','group'))].sum()
打印(a-b)

我将改变问题本身,以便更好地解释需要什么,因为我认为我第一次没有特别好地解释最终目标。

我的同事找到了解决方案,我认为解决方案也更好地解释了问题

import pandas as pd
import random
import math
import itertools

def n_per_group(n, n_groups):
    """find the size of each group when splitting n people into n_groups"""
    n_per_group = math.floor(n/n_groups)
    rem = n % n_per_group
    return [n_per_group if k<rem else n_per_group + 1 for k in range(n_groups)]

def assign_groups(n, n_groups):
    """split the n people in n_groups pretty evenly, and randomize"""
    n_per = n_per_group(n ,n_groups)
    groups = list(itertools.chain(*[i[0]*[i[1]] for i in zip(n_per,list(range(n_groups)))]))
    random.shuffle(groups)
    return groups

def group_diff(df, g1, g2):
    """calculate the between group score difference"""
    a = df.loc[df['group']==g1, ~df.columns.isin(('A','group'))].sum()
    b = df.loc[df['group']==g2, ~df.columns.isin(('A','group'))].sum()
    #print(a)
    return abs(a-b).sum()

def swap_groups(df, row1, row2):
    """swap the groups of the people in row1 and row2"""
    r1group = df.loc[row1,'group']
    r2group = df.loc[row2,'group']
    df.loc[row2,'group'] = r1group
    df.loc[row1,'group'] = r2group
    return df

def row_to_group(df, row):
    """get the group associated to a given row"""
    return df.loc[row,'group']

def swap_and_score(df, row1, row2):
    """
    given two rows, calculate the between group scores
    originally, and if we swap rows. If the score difference
    is minimized by swapping, return the swapped df, otherwise
    return the orignal (swap back)
    """
    #orig = df
    g1 = row_to_group(df,row1)
    g2 = row_to_group(df,row2)
    s1 = group_diff(df,g1,g2)
    df = swap_groups(df, row1, row2)
    s2 = group_diff(df,g1,g2)
    #print(s1,s2)
    if s1>s2:
        #print('swap')
        return df
    else:
        return swap_groups(df, row1, row2)

def pairwise_scores(df):
    d = []
    for i in range(n_groups):
        for j in range(i+1,n_groups):
            d.append(group_diff(df,i,j))
    return d

# one hot encode and copy
df_dum = pd.get_dummies(df, columns=['B', 'C', 'D']).copy(deep=True)

#drop extra cols as needed

groups = assign_groups(n, n_groups)
df_dum['group'] = groups

# iterate
for _ in range(5000):
    rows = random.choices(list(range(n)),k=2)
    #print(rows)
    df_dum = swap_and_score(df_dum,rows[0],rows[1])
    #print(pairwise_scores(df))

print(pairwise_scores(df_dum))

df['group'] = df_dum.group
df['orig_groups'] = groups

for i in range(n_groups):
        for j in range(i+1,n_groups):
            a = df_dum.loc[df_dum['group']==3, ~df_dum.columns.isin(('A','group'))].sum()
            b = df_dum.loc[df_dum['group']==0, ~df_dum.columns.isin(('A','group'))].sum()
            print(a-b)
将熊猫作为pd导入
随机输入
输入数学
进口itertools
每个组定义n个(n,n个组):
“”“将n个人分成n个组时查找每个组的大小”“”
每组n\u=数学楼层(n/n\u组)
rem=每组n%n
如果ks2:
#打印(‘交换’)
返回df
其他:
返回交换组(df,第1行,第2行)
def成对_分数(df):
d=[]
对于范围内的i(n_组):
对于范围内的j(i+1,n_组):
d、 附加(组_diff(df,i,j))
返回d
#一个热编码和复制
df_dum=pd.get_dummies(df,columns=['B','C','D'])。copy(deep=True)
#如有需要,多放些可乐
组=分配组(n,n组)
df_dum['group']=组
#迭代
对于范围内的(5000):
行=随机。选择(列表(范围(n)),k=2)
#打印(行)
df_dum=交换_和_分数(df_dum,第[0]行,第[1]行)
#打印(成对分数(df))
打印(成对分数(df_dum))
df['group']=df_dum.group
df['orig_groups']=组
对于范围内的i(n_组):
对于范围内的j(i+1,n_组):
a=df_dum.loc[df_dum['group']==3,~df_dum.columns.isin(('a','group'))].sum()
b=df_dum.loc[df_dum['group']==0,~df_dum.columns.isin(('A','group'))].sum()
打印(a-b)

我将改变问题本身,以便更好地解释所需内容,因为我认为我第一次没有很好地解释最终目标。

能否包括预期的输出?重新说明问题并包括示例输出。在花了一些时间研究和完善代码和问题之后,我找到了一篇论文om 20年前,这篇文章完美地陈述了问题并提出了解决问题的途径。你能包含预期的输出吗?重新陈述了问题并包含了示例输出。在花了一些时间研究和完善代码和问题之后,我发现20年前的一篇文章完美地陈述了问题并提出了解决问题的途径把它弄得乱七八糟。