55import io
66import pandas as pd
77
8- def create_data_export (survey_id : str ) -> str :
8+ def create_data_export (survey_id : str , incomplete_bool : bool = True ) -> str :
99 """Create a data export request for a given survey.
1010
1111 Args:
1212 survey_id (str): The ID of the survey to export.
13+ incomplete_bool (bool): Whether to export only responses that are still in progress.
1314 Raises:
1415 QualtricsAPIError: If there is an error during the request or unexpected response format.
1516 Returns:
@@ -18,7 +19,8 @@ def create_data_export(survey_id: str) -> str:
1819 print ("Creating data export request... " )
1920 endpoint = f"{ BASE_URL } /surveys/{ survey_id } /export-responses"
2021 payload = {
21- "format" : "csv"
22+ "format" : "csv" ,
23+ "exportResponsesInProgress" : incomplete_bool
2224 }
2325 try :
2426 response = requests .post (endpoint , headers = HEADERS , json = payload )
@@ -131,6 +133,30 @@ def check_inputs_validity(participant_study_id: str, embedded_data_field: str, s
131133 raise ValueError ("Invalid participant_study_id. It should be a non-empty string." )
132134 return True
133135
136+ def get_responses_as_df (survey_id : str , incomplete_bool : bool ) -> pd .DataFrame :
137+ """Wrapper function to request export, wait for it, download it, and convert to DataFrame.
138+
139+ Args:
140+ survey_id (str): The ID of the survey to get responses from.
141+ incomplete_bool (bool): Whether to get responses that are in progress or completed.
142+
143+ Returns:
144+ pd.DataFrame: The survey response data as a DataFrame.
145+ """
146+ # Request a data export
147+ request_id = create_data_export (survey_id , incomplete_bool = incomplete_bool )
148+
149+ # Ping the export report repeatedly until it's ready
150+ export_progress = 0.0
151+ while export_progress < 100 :
152+ export_progress = check_export_progress (request_id , survey_id , returns = "percent_complete" )
153+ time .sleep (1.5 )
154+
155+ # When export is complete, get the file ID
156+ file_id = check_export_progress (request_id , survey_id , returns = "fileID" )
157+ df = download_export (file_id , survey_id )
158+ return df
159+
134160def get_individual_progress (participant_study_id : str , embedded_data_field : str , survey_id : str ) -> float :
135161 """Wrapper function that gets the individual progress of a participant in a survey.
136162
@@ -146,34 +172,26 @@ def get_individual_progress(participant_study_id: str, embedded_data_field: str,
146172 # Check for invalid inputs
147173 check_inputs_validity (participant_study_id , embedded_data_field , survey_id )
148174
149- # Request a data export
150- request_id = create_data_export (survey_id )
151-
152- # Ping the export report repeatedly until it's ready
153- export_progress = 0.0
154- while export_progress < 100 :
155- export_progress = check_export_progress (request_id , survey_id , returns = "percent_complete" )
156- time .sleep (1 )
157-
158- # When export is complete, get the file ID
159- file_id = check_export_progress (request_id , survey_id , returns = "fileID" )
175+ completed_responses_df = get_responses_as_df (survey_id , incomplete_bool = False )
176+ incompleted_responses_df = get_responses_as_df (survey_id , incomplete_bool = True )
177+ df = pd .concat ([completed_responses_df , incompleted_responses_df ], ignore_index = True )
160178
161- if file_id :
162- df = download_export (file_id , survey_id )
163- print (df )
164- individual_progress = df [df [embedded_data_field ] == participant_study_id ]
165-
166- if not individual_progress .empty :
167- individual_progress = individual_progress ["Progress" ].values [0 ]
168- return individual_progress
169- else :
170- print (f"No data found for participant_study_id: { participant_study_id } in this survey." )
171- raise QualtricsAPIError ("Participant not found in survey data." )
179+ if not embedded_data_field in df .columns :
180+ raise QualtricsAPIError (f"Embedded data field '{ embedded_data_field } ' not found in survey data. Please check the field name." )
181+
182+ individual_progress = df [df [embedded_data_field ] == participant_study_id ]
183+ if not individual_progress .empty :
184+ individual_progress = individual_progress ["Progress" ].values [0 ]
185+ return individual_progress
186+ else :
187+ print (f"No data found for participant_study_id: { participant_study_id } in this survey." )
188+ raise QualtricsAPIError ("Participant not found in survey data." )
172189
173190if __name__ == "__main__" :
191+ # Example usage
174192 participant_study_id = "11111TEST11111"
175- survey_id = SURVEYIDS .my_test_survey2_id
193+ survey_id = SURVEYIDS .my_test_survey_id
176194 embedded_data_field = "study_id_child"
177195
178196 result = get_individual_progress (participant_study_id , embedded_data_field , survey_id )
179- print (result )
197+ print (result )
0 commit comments