Your Qualtrics export is a CSV — header row, then one row per respondent. Right now you open it in Excel. What if Python could read it directly?
summarize_group from yesterday gave me the statistics. But I was passing in dicts I made by hand. Real Qualtrics data comes as a CSV file, not a Python list.
Pyodide runs in-browser and has no file system to read from. So the teaching device here is clean: the CSV text arrives as a string argument. split('\n') gives you the rows. The first row is the header. The rest are data rows. You split(',') each row and zip it with the header to make a dict:
csv_text = "major,year,satisfaction\nEconomics,Junior,4.2\nBio,Senior,3.8"
rows = csv_text.strip().split('\n')
header = rows[0].split(',')
for row in rows[1:]:
values = row.split(',')
response = dict(zip(header, values))
print(response) # {'major': 'Economics', 'year': 'Junior', 'satisfaction': '4.2'}zip(header, values) — that pairs each column name with the value in the same position? Like two lists side by side?
Exactly. zip pairs items at the same index from two iterables. dict(zip(['a', 'b'], [1, 2])) gives {'a': 1, 'b': 2}. With header names and row values, it builds the response dict in one expression:
def parse_survey_csv(csv_text: str) -> list:
"""Parse CSV text into a list of response dicts."""
rows = csv_text.strip().split('\n')
header = rows[0].split(',')
responses = []
for row in rows[1:]:
values = [clean_response_text(v) for v in row.split(',')]
responses.append(dict(zip(header, values)))
print(f"Parsed {len(responses)} responses")
return responsesI'm using clean_response_text from Day 4 inside the list comprehension. The whole pipeline chains together — parse, clean, group, summarise.
Your Qualtrics export goes in as a string. Your methodology table comes out as a nested dict. No Excel, no pivot, no manual step.
Wait — I can pass this the actual CSV text from a Qualtrics export and it produces my cross-tab input. My thesis advisor wants the script.
clean_response_text normalises with replace(' ', '_'). That means "year_in_school" and "Year In School" become the same key. If your header has spaces, they get normalised too — which matters for the group_by_demographic call that follows.
The Pyodide executor has no file system. Lessons that "read a file" take the file contents as a string argument — the function is pure and testable.
rows = csv_text.strip().split('\n') # split on newlines
header = rows[0].split(',') # first row is the header
for row in rows[1:]: # remaining rows are data
values = row.split(',')
response = dict(zip(header, values))zip(a, b) in one linedict(zip(header, values)) pairs column names with values by position. If they have different lengths, zip stops at the shorter one.
Your Qualtrics export is a CSV — header row, then one row per respondent. Right now you open it in Excel. What if Python could read it directly?
summarize_group from yesterday gave me the statistics. But I was passing in dicts I made by hand. Real Qualtrics data comes as a CSV file, not a Python list.
Pyodide runs in-browser and has no file system to read from. So the teaching device here is clean: the CSV text arrives as a string argument. split('\n') gives you the rows. The first row is the header. The rest are data rows. You split(',') each row and zip it with the header to make a dict:
csv_text = "major,year,satisfaction\nEconomics,Junior,4.2\nBio,Senior,3.8"
rows = csv_text.strip().split('\n')
header = rows[0].split(',')
for row in rows[1:]:
values = row.split(',')
response = dict(zip(header, values))
print(response) # {'major': 'Economics', 'year': 'Junior', 'satisfaction': '4.2'}zip(header, values) — that pairs each column name with the value in the same position? Like two lists side by side?
Exactly. zip pairs items at the same index from two iterables. dict(zip(['a', 'b'], [1, 2])) gives {'a': 1, 'b': 2}. With header names and row values, it builds the response dict in one expression:
def parse_survey_csv(csv_text: str) -> list:
"""Parse CSV text into a list of response dicts."""
rows = csv_text.strip().split('\n')
header = rows[0].split(',')
responses = []
for row in rows[1:]:
values = [clean_response_text(v) for v in row.split(',')]
responses.append(dict(zip(header, values)))
print(f"Parsed {len(responses)} responses")
return responsesI'm using clean_response_text from Day 4 inside the list comprehension. The whole pipeline chains together — parse, clean, group, summarise.
Your Qualtrics export goes in as a string. Your methodology table comes out as a nested dict. No Excel, no pivot, no manual step.
Wait — I can pass this the actual CSV text from a Qualtrics export and it produces my cross-tab input. My thesis advisor wants the script.
clean_response_text normalises with replace(' ', '_'). That means "year_in_school" and "Year In School" become the same key. If your header has spaces, they get normalised too — which matters for the group_by_demographic call that follows.
The Pyodide executor has no file system. Lessons that "read a file" take the file contents as a string argument — the function is pure and testable.
rows = csv_text.strip().split('\n') # split on newlines
header = rows[0].split(',') # first row is the header
for row in rows[1:]: # remaining rows are data
values = row.split(',')
response = dict(zip(header, values))zip(a, b) in one linedict(zip(header, values)) pairs column names with values by position. If they have different lengths, zip stops at the shorter one.
You have her Qualtrics survey export as a CSV string and needs to convert it to a list of response dicts before running her demographic analysis. Write `parse_survey_csv(csv_text)` that splits the CSV text by newline, treats the first row as the header, and returns a list of dicts pairing each column name with its value.
Tap each step for scaffolded hints.
No blank-editor panic.