File size: 3,252 Bytes
e69d4e4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
"""Unit tests for the apply_logic_response_criterion function."""

import copd
import numpy as np
import pandas as pd
import pytest


@pytest.fixture
def exacerbation_event():
    """Dataframe index (27) of the exacerbation event of interest."""
    return 27


@pytest.fixture
def first_pro_response():
    """Dataframe index (8) of the first weekly PRO response."""
    return 8


@pytest.fixture
def second_pro_response(first_pro_response):
    """Dataframe index of the second weekly PRO response. Seven days after first."""
    return first_pro_response + 7


@pytest.fixture
def input_df(exacerbation_event):
    """Sample input dataframe template - specific cases to be added in each test.

    This initial dataframe has no PRO responses between the initial exac and the event of
    interest with DaysSinceLastExac=25. Interim PRO responses should be added in tests.
    """
    df = pd.DataFrame({'PatientId': ['1'] * 31,
                       'DateOfEvent': pd.date_range('2022-01-01', '2022-01-31'),
                       'Q5Answered': [0] * 31,
                       'NegativeQ5': [np.nan] * 31,
                       'IsExac': [0] * 31,
                       'DaysSinceLastExac': [-1, -1, -1] + list(np.arange(1, 26)) +
                       list(np.arange(1, 4))})
    # Add initial event to simulate DaysSinceLastExac restart from 1
    df.loc[2, 'Q5Answered'] = 1
    df.loc[2, 'NegativeQ5'] = 0
    df.loc[2, 'IsExac'] = 1
    # Add event of interest (DaysSinceLastExac = 25)
    df.loc[exacerbation_event, 'Q5Answered'] = 1
    df.loc[exacerbation_event, 'NegativeQ5'] = 0
    df.loc[exacerbation_event, 'IsExac'] = 1

    # Add a negative response after the event of interest (should not be counted)
    df.loc[exacerbation_event + 2, 'Q5Answered'] = 1
    df.loc[exacerbation_event + 2, 'NegativeQ5'] = 1
    return df


def test_output_equals_expected_criterion_failed(input_df, exacerbation_event):
    """Test output is as expected for failed LOGIC response criterion."""
    # Output should be same as input with additional RemoveExac column
    expected_df = input_df.copy()
    # Insert RemoveExac column with exac flagged for removal
    expected_df['RemoveExac'] = np.nan
    expected_df.loc[exacerbation_event, 'RemoveExac'] = 1
    output_df = copd.apply_logic_response_criterion(input_df)
    pd.testing.assert_frame_equal(output_df, expected_df)


def test_output_equals_expected_criterion_passed(
        input_df, exacerbation_event, first_pro_response, second_pro_response):
    """Test output is as expected for passed LOGIC response criterion."""
    # Add PRO responses needed to pass LOGIC criterion
    input_df.loc[first_pro_response, 'Q5Answered'] = 1
    input_df.loc[first_pro_response, 'NegativeQ5'] = 1
    input_df.loc[second_pro_response, 'Q5Answered'] = 1
    input_df.loc[second_pro_response, 'NegativeQ5'] = 1

    # Output should be same as input with additional RemoveExac column
    expected_df = input_df.copy()
    # Insert RemoveExac column with exac flagged for removal
    expected_df['RemoveExac'] = np.nan
    expected_df.loc[exacerbation_event, 'RemoveExac'] = 0
    output_df = copd.apply_logic_response_criterion(input_df)
    pd.testing.assert_frame_equal(output_df, expected_df)