代码之家  ›  专栏  ›  技术社区  ›  The Unfun Cat

当行元组具有不同的数据类型时根据假设生成的数据帧排序

  •  2
  • The Unfun Cat  · 技术社区  · 7 年前

    我用的是:

    from hypothesis.extra.pandas import columns, data_frames, column
    import hypothesis.strategies as st
    
    positions = st.integers(min_value=0, max_value=int(1e7))
    strands = st.sampled_from("+ -".split())
    data_frames(columns=columns(["Start", "End"], dtype=int),
                rows=st.tuples(positions, positions).map(sorted)).example()
    

    它给予

         Start      End
    0   589492  6620613
    1  5990807  8083222
    2   252458  8368032
    3  1575938  5763895
    4  4689113  9133040
    5  7439297  8646668
    6   838051  1886133
    

    但是,我想添加第三列,Strand to the data,正如上面使用策略生成的那样。然后停止工作:

    data_frames(columns=columns(["Start", "End", "Strands"], dtype=int),
                rows=st.tuples(positions, positions, strands).map(sorted)).example()
    

    它给出了错误

    TypeError: '<' not supported between instances of 'str' and 'int'
    

    这是由于int和str的元组排序。我该怎么解决?

    我可以让假设生成一个包含pos、pos、strand-int的数据帧,其中strand-int为0或1,并在测试中将其转换为“-”或“+”,但感觉很恶心。

    2 回复  |  直到 7 年前
        1
  •  2
  •   The Unfun Cat    7 年前

    最佳方法

    better_dfs_min = data_frames(index=range_indexes(min_size=better_df_minsize),
                                 columns=[column("Chromosome", chromosomes_small),
                                          column("Start", elements=small_lengths),
                                          column("End", elements=small_lengths),
                                          column("Strand", strands)])
    
    
    @st.composite()
    def dfs_min(draw):
        df = draw(better_dfs_min)
        df.loc[:, "End"] += df.Start
        return df
    
    @given(df=dfs_min())
    def test_me(df):
        print(df)
        assert 0
    

    首次尝试:

    from hypothesis.extra.pandas import columns, data_frames, column
    import hypothesis.strategies as st
    
    def mysort(tp):
    
        key = [-1, tp[1], tp[2], int(1e10)]
    
        return [x for _, x in sorted(zip(key, tp))]
    
    positions = st.integers(min_value=0, max_value=int(1e7))
    strands = st.sampled_from("+ -".split())
    chromosomes = st.sampled_from(elements=["chr{}".format(str(e)) for e in list(range(23)) + "X Y M".split()])
    
    data_frames(columns=columns(["Chromosome", "Start", "End", "Strand"], dtype=int), rows=st.tuples(chromosomes, positions, positions, strands).map(mysort)).example()
    

    结果:

      Chromosome    Start      End Strand
    0      chr13  5660600  6171569      -
    1       chrY  3987154  5435816      +
    2      chr11  4659655  4956997      +
    3      chr14   239357  8566407      +
    4       chr3  3200488  9337489      +
    5       chr8   304886  1078020      +
    

    必须有更好的方法来做这件事,而不是实现你自己的分类…我的排序依赖于开始和结束的整数介于0和int(1e10)-1之间,这让人觉得恶心。

        2
  •  2
  •   Zac Hatfield-Dodds    7 年前

    欺骗!

    做你的第一行测试 df.End += df.Start ,结束将始终大于开始(假设为正整数)。如果有更具体的大小限制,请描述 end 假设所需的差异,然后使用这个技巧。

    您还可以使用 @st.composite 内联执行此操作的decorator。不过,如果你要用它进行多次测试,我认为这是值得的,但这是一个风格问题,而不是实质问题。

    推荐文章