如何从4个csv文件中随机采样,以便在Python中每个csv文件中按顺序显示的行数不超过2/3

如何从4个csv文件中随机采样,以便在Python中每个csv文件中按顺序显示的行数不超过2/3,python,csv,random,Python,Csv,Random,大家好,我对python非常陌生,我正在尝试创建一个程序,从CSV文件中随机抽取一个样本,并根据一些条件生成一个新文件。到目前为止,我所做的工作可能过于复杂,效率低下(尽管不需要) 我有4个CSV文件,总共包含264行,其中每一整行都是唯一的,尽管它们在某些列中共享公共值。 csv1=72行,csv2=72行,csv3=60行,csv4=60行。我需要采取160行随机抽样,这将使4块40,其中在每个块10必须来自每个csv文件。棘手的是,在最终文件中,同一CSV文件中最多只能按顺序显示2或3行

大家好,我对python非常陌生,我正在尝试创建一个程序,从CSV文件中随机抽取一个样本,并根据一些条件生成一个新文件。到目前为止,我所做的工作可能过于复杂,效率低下(尽管不需要)

我有4个CSV文件,总共包含264行,其中每一整行都是唯一的,尽管它们在某些列中共享公共值。 csv1=72行,csv2=72行,csv3=60行,csv4=60行。我需要采取160行随机抽样,这将使4块40,其中在每个块10必须来自每个csv文件。棘手的是,在最终文件中,同一CSV文件中最多只能按顺序显示2或3行

到目前为止,我已设法从每个CSV中随机抽取40个样本(仅使用
random.sample
)并将它们输出到4个新的CSV文件中。然后我将每个csv拆分为4个新文件,每个文件包含10行,这样我就可以将每个csv放在一个单独的文件夹中(1-4)。所以我现在有4个文件夹,每个文件夹包含4个csv文件。现在我需要组合这些,以便来自原始CSV文件的行不会重复超过2或3次,并且行顺序将尽可能随机。这就是我完全迷路的地方,我假设我应该将每个文件夹中的4个文件合并(我可以这样做),然后重新采样或在循环中洗牌,直到满足条件,或者类似的事情,但我不确定如何继续,或者我是以完全错误的方式进行的。任何人能给我的任何帮助都将不胜感激,我可以提供任何必要的进一步细节

var_start = 1
total_condition_amount_start = 1
    while (var_start < 5):
    with open("condition"+`var_start`+".csv", "rb") as population1:
            conditions1 = [line for line in population1]
            random_selection1 = random.sample(conditions1, 40)
            with open("./temp/40cond"+`var_start`+".csv", "wb") as temp_output:
                temp_output.write("".join(random_selection1))
            var_start = var_start + 1



while (total_condition_amount_start < total_condition_amount):

    folder_no = 1
    splitter.split(open("./temp/40cond"+`total_condition_amount_start`+".csv", 'rb'));

    shutil.move("./temp/output_1.csv", "./temp/block"+`folder_no`+"/output_"+`total_condition_amount_start`+".csv")
    folder_no = folder_no + 1
    shutil.move("./temp/output_2.csv", "./temp/block"+`folder_no`+"/output_"+`total_condition_amount_start`+".csv")
    folder_no = folder_no + 1
    shutil.move("./temp/output_3.csv", "./temp/block"+`folder_no`+"/output_"+`total_condition_amount_start`+".csv")
    folder_no = folder_no + 1
    shutil.move("./temp/output_4.csv", "./temp/block"+`folder_no`+"/output_"+`total_condition_amount_start`+".csv")

    total_condition_amount_start = total_condition_amount_start + 1
var\u start=1
总条件金额开始=1
而(var_开始<5):
以open(“条件”+`var\u start`+.csv”、“rb”)作为填充1:
条件1=[填充1中的行对应行]
random_selection1=random.sample(条件1,40)
打开(“./temp/40cond”+`var\u start`+.csv”、“wb”)作为温度输出:
临时输出写入(“.join(随机选择1))
var\u start=var\u start+1
而(总条件金额开始<总条件金额):
文件夹编号=1
splitter.split(打开(“./temp/40cond”+`total\u condition\u amount\u start`+.csv”,'rb');
shutil.move(“/temp/output\U 1.csv”、“/temp/block”+`文件夹号“+”/output\U”+`总条件\U金额\U开始“+”.csv”)
文件夹编号=文件夹编号+1
shutil.move(“/temp/output\U 2.csv”、“/temp/block”+`文件夹号“+”/output\U”+`总条件\U金额\U开始“+”.csv”)
文件夹编号=文件夹编号+1
shutil.move(“/temp/output\U 3.csv”、“/temp/block”+`文件夹号“+”/output\U”+`总条件\U金额\U开始“+”.csv”)
文件夹编号=文件夹编号+1
shutil.move(“/temp/output\U 4.csv”、“/temp/block”+`文件夹号“+”/output\U”+`总条件\U金额\U开始“+”.csv”)
总条件金额开始=总条件金额开始+1

您可能应该尝试使用CSV内置库:

这样,您就可以将每个文件作为字典列表来处理,这将使您的任务更容易

from random import randint, sample, choice


def create_random_list(length):
    return [randint(0, 100) for i in range(length)]

# This should be your list of four initial csv files
# with the 264 rows in total, read with the csv lib
lists = [create_random_list(264) for i in range(4)]

# Take a randomized sample from the lists
lists = map(lambda x: sample(x, 40), lists)

# Add some variables to the
lists = map(lambda x: {'data': x, 'full_count': 0}, lists)


final = [[] for i in range(4)]
for l in final:
    prev = None
    count = 0
    while len(l) < 40:
        current = choice(lists)

        if current['full_count'] == 10 or (current is prev and count == 3):
            continue
        # Take an item from the chosen list if it hasn't been used 3 times in a
        # row or is already used 10 times. Append that item to the final list

        total_left = 40 - len(l)
        maxx = 0
        for i in lists:
            if i is not current and 10 - i['full_count'] > maxx:
                maxx = 10 - i['full_count']

        current_left = 10 - current['full_count']
        max_left = maxx + maxx/3.0

        if maxx > 3 and total_left <= max_left:
            # Make sure that in te future it can still be split in to sets of
            # max 3
            continue

        l.append(current['data'].pop())
        count += 1
        current['full_count'] += 1

        if current is not prev:
            count = 0
            prev = current

    for li in lists:
        li['full_count'] = 0
从随机导入随机输入,样本,选择
def创建随机列表(长度):
返回[randint(0,100)表示范围(长度)内的i]
#这应该是您的四个初始csv文件列表
#总共有264行,使用csv库读取
lists=[为范围(4)中的i创建\u随机\u列表(264)]
#从列表中随机抽取样本
列表=映射(λx:sample(x,40),列表)
#将一些变量添加到
lists=map(lambda x:{'data':x,'full_count':0},列表)
最终=[]对于范围(4)中的i
对于期末考试中的l:
prev=无
计数=0
而len(l)<40:
当前=选项(列表)
如果当前['full_count']=10或(当前为上一个且计数=3):
持续
#从所选列表中选取一个项目,如果该项目在一个项目中未使用过3次
#行或已使用10次。将该项附加到最终列表中
总左=40-透镜(l)
maxx=0
对于列表中的i:
如果i不是当前值且10-i['full_count']>maxx:
maxx=10-i[“完整计数”]
当前左=10-当前[“完整计数”]
最大左=最大x+最大x/3.0

如果maxx>3且总剩余,您可以将整个数据保存在内存中吗?因为您实际上不需要处理文件,所以如果您只需读取4个文件中的所有数据并将其混合,然后写入输出文件,将变得更简单、更快。我最初尝试过,但正如我所说,我对这一点非常陌生,这在我的头脑中更容易想象,因为我可以看到并检查我的输出文件,以确保事情按应有的方式运行。好的,我明白了。你用的是什么IDE?有一些可以让你在内存中保存的东西上做到这一点,例如Spyder(我喜欢使用它)。我不确定是否理解您的问题,但是否可以将所有行按如下方式放在一起:
rowF1、rowF2、rowF3、rowF4、rowF1、rowF2…
(所有文件中的交替行)然后只选择其中的一些行?这样,你就不会从同一个文件中一行接一行地出现两行或更多行。不过,我使用的是Komodo,没有什么特别的原因。问题是,这个csv文件是心理学实验的输入,因此,如果出现3个以上的相同条件,则他们对第4个条件做出相同响应的可能性会增加,即使是不同的,也会使数据倾斜(这种可能性增加,行数相同的行数越多)。根据您的建议,可能会发生类似的情况,因为它们会陷入一种响应模式,并再次扭曲数据。为了更好地可视化嵌套列表,请使用
pprint
我尝试了使用csv库的方法,我发布的内容只是我所希望的工作方式,在我的编辑器中,我有另外100多行注释掉的代码,这些代码来自我一直在尝试的不同东西。我可以使用csv库打开文件并编写新文件,但我不确定