Skip to content

Commit

Permalink
Fix code formatting issues
Browse files Browse the repository at this point in the history
  • Loading branch information
sabinleee committed Sep 6, 2024
1 parent 8394cf9 commit 201471a
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 43 deletions.
46 changes: 28 additions & 18 deletions src/pingouin/nonparametric.py
Original file line number Diff line number Diff line change
Expand Up @@ -996,7 +996,9 @@ def quades(data, dv, within, group):
"""
# Validate input types
if not all(isinstance(param, str) for param in [dv, within, group]):
raise TypeError("Parameters 'dv', 'within', and 'group' must be strings representing column names.")
raise TypeError(
"Parameters 'dv', 'within', and 'group' must be strings representing column names."
)

# Ensure columns exist in the data
if not all(col in data.columns for col in [dv, within, group]):
Expand All @@ -1008,26 +1010,28 @@ def quades(data, dv, within, group):
raise ValueError("At least two groups are required to perform Quade's test.")

# Step 1: Calculate the change scores (Posttest - Pretest)
data['change_score'] = data[dv] - data[within]
data["change_score"] = data[dv] - data[within]

# Handle zero variance case (all change scores are zero)
if np.all(data['change_score'] == 0):
if np.all(data["change_score"] == 0):
F_stat, p_value = "N/A", "N/A"
else:
# Step 2: Rank the scores
data['rank_change'] = scipy.stats.rankdata(data['change_score'])
data['rank_pretest'] = scipy.stats.rankdata(data[within])
data["rank_change"] = scipy.stats.rankdata(data["change_score"])
data["rank_pretest"] = scipy.stats.rankdata(data[within])

# Step 3: Handle identical ranks case
if np.all(data['rank_pretest'] == data['rank_pretest'][0]):
data['residuals'] = data['rank_change'] - np.mean(data['rank_change'])
if np.all(data["rank_pretest"] == data["rank_pretest"][0]):
data["residuals"] = data["rank_change"] - np.mean(data["rank_change"])
else:
# Perform linear regression
slope, intercept, _, _, _ = scipy.stats.linregress(data['rank_pretest'], data['rank_change'])
data['residuals'] = data['rank_change'] - (slope * data['rank_pretest'] + intercept)
slope, intercept, _, _, _ = scipy.stats.linregress(
data["rank_pretest"], data["rank_change"]
)
data["residuals"] = data["rank_change"] - (slope * data["rank_pretest"] + intercept)

# Step 4: Ensure there are at least two groups with residuals
residuals_by_group = [data.loc[data[group] == g, 'residuals'].values for g in unique_groups]
residuals_by_group = [data.loc[data[group] == g, "residuals"].values for g in unique_groups]
if len(residuals_by_group) < 2:
raise ValueError("At least two groups are required to perform Quade's test.")

Expand All @@ -1036,16 +1040,22 @@ def quades(data, dv, within, group):
F_stat, p_value = f"{F_statistic:.3f}", f"{p_value:.4f}"

# Step 5: Calculate and format Means (M) and Standard Deviations (SD) for Pretest and Posttest
summary_stats = data.groupby(group).agg(
PretestM_SD=(within, lambda x: f"{x.mean():.2f} ({x.std():.2f})"),
PosttestM_SD=(dv, lambda x: f"{x.mean():.2f} ({x.std():.2f})")
).reset_index()
summary_stats = (
data.groupby(group)
.agg(
PretestM_SD=(within, lambda x: f"{x.mean():.2f} ({x.std():.2f})"),
PosttestM_SD=(dv, lambda x: f"{x.mean():.2f} ({x.std():.2f})"),
)
.reset_index()
)

# Step 6: Add F-statistic and p-value
summary_stats['F'] = [F_stat if g == unique_groups[0] else '' for g in summary_stats[group]]
summary_stats['p-value'] = [p_value if g == unique_groups[0] else '' for g in summary_stats[group]]
summary_stats["F"] = [F_stat if g == unique_groups[0] else "" for g in summary_stats[group]]
summary_stats["p-value"] = [
p_value if g == unique_groups[0] else "" for g in summary_stats[group]
]

# Rename the group column
final_table = summary_stats.rename(columns={group: 'Group'})
final_table = summary_stats.rename(columns={group: "Group"})

return final_table
return final_table
52 changes: 27 additions & 25 deletions tests/test_nonparametric.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,66 +249,68 @@ def test_quades(self):
"""Test function quades"""
# Basic test case
data = {
'group': ['A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'B'],
'pretest': [50, 60, 45, 70, 65, 55, 75, 60, 80, 70],
'posttest': [52, 63, 47, 72, 67, 70, 95, 85, 100, 95]
"group": ["A", "A", "A", "A", "A", "B", "B", "B", "B", "B"],
"pretest": [50, 60, 45, 70, 65, 55, 75, 60, 80, 70],
"posttest": [52, 63, 47, 72, 67, 70, 95, 85, 100, 95],
}
df = pd.DataFrame(data)

result = quades(data=df, dv='posttest', within='pretest', group='group')
result = quades(data=df, dv="posttest", within="pretest", group="group")

# Verify results
assert result.loc[result['Group'] == 'A', 'F'].values[0] == '12.635'
assert result.loc[result['Group'] == 'A', 'p-value'].values[0] == '0.0075'
assert result.loc[result["Group"] == "A", "F"].values[0] == "12.635"
assert result.loc[result["Group"] == "A", "p-value"].values[0] == "0.0075"

# Check if the output is a DataFrame and has the correct column names
assert isinstance(result, pd.DataFrame)
assert 'Group' in result.columns
assert 'F' in result.columns
assert 'p-value' in result.columns
assert "Group" in result.columns
assert "F" in result.columns
assert "p-value" in result.columns

# Additional test cases

# Edge case: Empty DataFrame
empty_df = pd.DataFrame(columns=['group', 'pretest', 'posttest'])
empty_df = pd.DataFrame(columns=["group", "pretest", "posttest"])
try:
quades(data=empty_df, dv='posttest', within='pretest', group='group')
quades(data=empty_df, dv="posttest", within="pretest", group="group")
except ValueError:
pass # Expect an error for an empty DataFrame

# Edge case: Only one group
one_group_df = pd.DataFrame({
'group': ['A', 'A', 'A', 'A', 'A'],
'pretest': [50, 60, 45, 70, 65],
'posttest': [52, 63, 47, 72, 67]
})
one_group_df = pd.DataFrame(
{
"group": ["A", "A", "A", "A", "A"],
"pretest": [50, 60, 45, 70, 65],
"posttest": [52, 63, 47, 72, 67],
}
)
try:
quades(data=one_group_df, dv='posttest', within='pretest', group='group')
quades(data=one_group_df, dv="posttest", within="pretest", group="group")
except ValueError:
pass # Expect an error when there is only one group

# Data type validity test: Incorrect data type
try:
quades(data=df, dv=123, within='pretest', group='group')
quades(data=df, dv=123, within="pretest", group="group")
except TypeError:
pass # Expect an error when 'dv' is not a string

# Test for non-existent column
try:
quades(data=df, dv='nonexistent', within='pretest', group='group')
quades(data=df, dv="nonexistent", within="pretest", group="group")
except KeyError:
pass # Expect an error when the specified column does not exist

# Special case test: All 'within' values are the same
df_same_within = df.copy()
df_same_within['pretest'] = 60
result = quades(data=df_same_within, dv='posttest', within='pretest', group='group')
df_same_within["pretest"] = 60
result = quades(data=df_same_within, dv="posttest", within="pretest", group="group")
assert isinstance(result, pd.DataFrame) # The result should still be a DataFrame
assert 'F' in result.columns and 'p-value' in result.columns
assert "F" in result.columns and "p-value" in result.columns

# Special case test: All change scores are zero
df_zero_change = df.copy()
df_zero_change['posttest'] = df_zero_change['pretest']
result = quades(data=df_zero_change, dv='posttest', within='pretest', group='group')
df_zero_change["posttest"] = df_zero_change["pretest"]
result = quades(data=df_zero_change, dv="posttest", within="pretest", group="group")
assert isinstance(result, pd.DataFrame) # The result should still be a DataFrame
assert 'F' in result.columns and 'p-value' in result.columns
assert "F" in result.columns and "p-value" in result.columns

0 comments on commit 201471a

Please sign in to comment.