Как реализовать зависимые столбцы в фреймах данных гипотез

Я использую фреймы данных гипотез для реализации фрейма данных, в котором start_time и end_time - два столбца. Вот кусок:

import hypothesis.strategies as st
import logging
import datetime

from hypothesis import given
from hypothesis.extra.pandas import column, data_frames, range_indexes

current_time = datetime.datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)

datetime_st = st.integers(
    min_value=(current_time + datetime.timedelta(hours=4)).timestamp(),
    max_value=(current_time + datetime.timedelta(hours=20)).timestamp(),
)

df_columns = {
    # other fields omitted
    "start_time": {"elements": datetime_st, "unique": False},
    "end_time": {"elements": datetime_st, "unique": False},
}
test_dfs = data_frames(
    index=range_indexes(min_size=20, max_size=100),
    columns=[column(key, **value) for key, value in df_columns.items()],
)

@given(df=test_dfs)
def test_hyothesis(df):
    logging.info(df)
    assert 1

Я не могу найти решение, чтобы утверждать, что каждое start_time должно быть больше соответствующего end_time по крайней мере на дельту. Я пробовал composite, но не уверен, как реализовать это в каждой строке dataframes.

Есть ли способ, которым я, как правило, применяю дельту при инициализации start_time и end_time?


person GGJON    schedule 23.06.2020    source источник


Ответы (1)


Вот способ сгенерировать фрейм данных из двух столбцов с отметками времени, где разница между первым и вторым составляет не менее 3600 секунд (или какое-то другое количество времени). Я использую st.flatmap для этого.

import hypothesis.strategies as st
from hypothesis.extra.pandas import column, data_frames, range_indexes, columns

current_time = datetime.datetime.now().replace(hour=0, minute=0, second=0, microsecond=0).timestamp()

MIN_DIFF_SECONDS = 3600

two_timestamps_with_diff = st.integers(
    min_value = current_time + 3600 * 4, 
    max_value = current_time + 4600 * 20).flatmap(
    lambda n: st.tuples(
       st.integers(min_value = n, max_value=n), 
       st.integers(min_value = n + MIN_DIFF_SECONDS, max_value = n + 3600*10)
   ))

# sample code to examine the results of this strategy
# for _ in range(10):
#     x, y = two_timestamps_with_diff.example()
#     print(x, y, y-x)
    
test_dfs = data_frames(
    index=range_indexes(min_size=20, max_size=100),
    columns=columns(["start_time", "end_time"], dtype=int),
    rows=two_timestamps_with_diff, 
)

# sample code to examine the results of this strategy
# res = test_dfs.example()
# res.assign(d = res.end_time - res.start_time)

# a test with an assertion that validates this constraint. 
@given(df=test_dfs)
def test_hyothesis(df):
    logging.info(df)
    assert ((df.end_time - df.start_time) >= MIN_DIFF_SECONDS).all()
    
# run the test. It passes. 
test_hyothesis()

Если вы хотите добавить дополнительные столбцы в автоматически сгенерированный фрейм данных, выполните следующие действия (в этом примере новыми столбцами являются «a» и «b»):

from hypothesis.strategies import composite

@composite
def test_df_with_additional_columns(draw, elements=test_dfs):
    df = draw(test_dfs)
    
    class GetIndex(st.SearchStrategy[pd.core.indexes.range.RangeIndex]): 
        def do_draw(self, _):
            return df.index    
    
    more_col_strategy = data_frames([column('A', dtype=int), 
                                     column('B', dtype=float)], 
                                    index = GetIndex()
                                   )
    
    more_cols = draw(more_col_strategy)
    
    return pd.concat([df, more_cols], axis=1)

test_df_with_additional_columns().example()
person Roy2012    schedule 23.06.2020
comment
Это работает после создания файла df. Есть ли способ применить это утверждение как правило при инициализации start_time и end_time? - person GGJON; 24.06.2020
comment
Ага. Теперь я понимаю, что вы ищете. Вы хотите сгенерировать только данные, в которых start_time + CONSTANT ‹end_time? - person Roy2012; 24.06.2020
comment
Взгляните на этот новый ответ. Сообщите мне, если это поможет. (вопрос, кстати, прикольный :) - person Roy2012; 24.06.2020
comment
Спасибо! Это решает это. Вчера я был занят добавлением дополнительных столбцов к той же логике. - person GGJON; 25.06.2020
comment
Поднимая этот поток, я не могу реализовать случай, когда в df_columns есть другие поля, кроме start_time и end_time - person GGJON; 08.07.2020
comment
Не могли бы вы привести пример других столбцов, которые вы хотели бы создать? - person Roy2012; 08.07.2020
comment
"name": {"elements": some_name_function, "unique": True}, "field1": {"elements": field1_fucntion, "unique": False},... и так далее. Они не зависят от start_time и end_time - person GGJON; 08.07.2020