LLMRpanel 0.6.3
CRAN release: 2026-10-28
The bundled ANES personas
anes_2024_personasnow ships with LLMRpanel, and the examples, the Studio, and the tests use it in place ofLLMR::anes_2024_personas. FocusGroup ships an identical copy. The data were rebuilt from the May 19, 2026 Full Release of the ANES 2024 Time Series Study with corrected coding, so the 100 respondents and theirideology_scorevalues differ from those in LLMR’s copy. The old build had turned the middle answers of six seven-point scales into missing values, which also tilted the selection of respondents and the ideology scores toward people who chose the ends of those scales. It kept four immigration-policy labels that the Stata file cuts at 80 characters, interviewer notes such as “{VOL}”, two items from the spouse/partner survey that gave 14 personas their partner’s answers, and six fields that were empty for everyone because their items were asked only on paper or only of the GSS re-interview sample, which this release does not include. Answers on the six scales now read “5 on a scale from 1 (…) to 7 (…)” and feeling thermometers “70 on a 0-100 feeling thermometer”.?anes_2024_personasdocuments the coding and the selection.Changed handles:
demo_community_typeis replaced bydemo_rural_urban_identity, and the three confidence itemsatt_val_confidence_in_the_supreme_co,att_val_confidence_in_the_scientific, andatt_val_confidence_in_the_pressbyatt_val_trust_in_the_judiciary,att_val_trust_in_scientists, andatt_val_trust_in_traditional_media.att_val_general_happinessandatt_val_importance_of_remaining_a_deare gone.demo_home_ownershipnow comes from the item asked of everyone, so its values include “Rented for cash”; the MAGA thermometer and satisfaction with democracy come from post-election items asked of every respondent. The frame has 123 columns, 17 of them demographic.
Rendering of persona values
Missing-data labels are left out of the persona text.
panel_from_personas()andpanel_from_data()gainna_strings, regular expressions that mark a value or value label as missing;NULL, the default, uses the patterns of FocusGroup’sfg_default_na_strings(). Before, a frame decoded withhaven::as_factor(), as the help ofas_persona_frame()advised, gave personas answers such as “-9. Refused”, “-3. RESTRICTED”, and “-8. Don’t know”. A few patterns are anchored: “Error” must be the whole label and “RESTRICTED” its first word, so “Terrorism” and “There is an error” are kept. A value or value label that matches is left out when it carries a missing-data code (negative, or 90 and above: “-9 Refused”, “[-8] Don’t know”, “998. Don’t know (where to rate)”) or says nothing but such wording once codes, interviewer markers (“{VOL}”, “(VOL)”), and asides in parentheses are set aside (“Refused to answer”, “Don’t know/Refused (VOL.)”). Answers that use such words (“2. Refused to take sides”, “I refused to answer the door”) are kept. FocusGroup decides by the same rule. Values left out are reported.panel_from_personas()restores the dictionary and demographic fields ofanes_2024_personasfrom the package’s copy, with a message, when base subsetting (x[, j],subset()) has dropped them; before, the demographics of such a subset were rendered as questionnaire answers under their raw handles.Identifier columns also include ResponseId, participant_id, subject_id, user_id, PROLIFIC_PID, workerId, caseno, and QKEY.
Labeled survey columns, as
haven::read_dta()andhaven::read_sav()return them, are decoded from their value labels, without haven. A labeled code is shown as its label without the code prefix, and an unlabeled code on a scale labeled only at its ends as “5 on a scale from 1 (…) to 7 (…)”, where a scale centered on zero runs from -m to m even when its midpoint is labeled. Before, such a column was rendered as bare codes (“spend – 5”), or stopped with an error when haven was not loaded. An unlabeled negative code is left out as missing, and any other unlabeled code is shown as the code, each with a warning naming the column. Factor levels ashaven::as_factor()writes them, and character columns asas.character(haven::as_factor())writes them, are decoded by the same rules, and code prefixes (“1.”) are removed from factor levels and character values.Numbers are written in full: “income 100000”, not “income 1e+05”.
Identifier columns (
id,caseid,case_id,respondent_id,respid,resp_id,persona_id,uid,record_id, androw_id, ignoring case, and columns whose variable label calls them a case or respondent ID, as the ANES label of V240001 does), the column named byweights, a column namedpersona, andideology_scoreare never rendered. Before,panel_from_personas()andpanel_from_data()without a template wrote them into the persona text (“id – 101; respondent_id – R1”, “wt – 1.2”), andpanel_from_data()wrote theideology_scoreof the bundled personas. They remain columns of the panel where they were before. Apersona_templatethat names one of them is an error.Values left out of the persona text are reported in a message that names each field and the number of personas without it. Before, they were dropped silently, and
panel_from_data()without a template wrote “column: NA”. A template placeholder without a value is now filled with nothing, with a warning; before, it showed “NA”.panel_from_personas()gainsquestions, question texts named by column, which take precedence over the frame’s dictionary. When column names stand in for the questions of stated answers, as when column subsetting has dropped a frame’s dictionary, a warning lists the columns.A value label exactly 80 characters long draws a warning: Stata files cut value labels at that length.
The demographic columns of a panel from
panel_from_personas()hold the values as the personas state them, and the margins both constructors cite count those values, so a missing-data label is no longer a category.In
run_panel_studio(), the persona preview, now titled “Selected persona as sent”, shows the text sent with each request, rendered from the selected fields only; before, it showed every field while only the selected ones were sent.ideology_score, which is never rendered, is no longer offered as a field.
LLMRpanel 0.6.2
The help and vignette describe each persona-item pair as an independent request with option-order randomization; claims about item-order randomization and sample-size planning are removed.
run_panel_studio()refuses malformed population margins and benchmark shares, naming the entry, instead of dropping it.panel_from_personas()draws the selected respondent whenrowsselects a single row; it used to sample from rows 1 to that number instead. Draws from two or more rows are unchanged.panel_from_personas()stops with “rowsindices must be whole numbers between 1 and nrow(data), with no NA.” whenrowsis fractional, character, or a factor. Before,rows = c(1.9, 3.7)selected rows 1 and 3,rows = "3"selected row 3, and a factor selected the rows numbered by its level codes. A fractionalnstops with “nmust be one whole number of at least 1.”; before,n = 2.5drew two personas.panel_from_personas()andpanel_from_data()record the source rows they drew in a newsource_rowsattribute, giving for each persona inpersona_idorder the row ofdatait came from.as_tibble()drops it along withmarginsandsource.conjoint_amce()records each attribute’s reference level in a newreferenceattribute and prints the reference levels below the header. The reference is still the first declared level present in the estimation data. When that is not the first declared level, for example because every execution showing it failed, the function warns “Some declared conjoint levels are absent from the estimation data.” and names the level that took its place; before, the baseline changed without a message. The same warning names any other declared level that is absent and so has no row.conjoint_amce()stores the number of personas whose responses entered the estimate, the clusters behind its standard errors, in a newn_clustersattribute and prints it besiden_respondents.n_respondentsstill counts every persona administered, including those whose responses all failed or did not parse, so the two differ after such failures.item_likert(),item_choice(), anditem_open()stop with “idmust be one nonempty character string, not …” when the id is missing, empty, or longer than one string, and with the same message fortext. Before, anNAid or question was accepted and sent as the text “NA”, and a longer vector was accepted and failed later or built a malformed request.item_choice()anditem_likert()stop with “optionshas a missing or empty label at position …” (or “scalehas …”) when a label isNAor empty, and with “optionshas labels that replies cannot tell apart: …” when two labels are equal after ignoring case and surrounding spaces, which is how replies are matched to labels. Before, such labels were accepted: a repeated Likert label made its score ambiguous, and a reply matching two labels was assigned to the first. A label set that is not character or has fewer than two labels stops with “must be a character vector of at least two labels” instead of astopifnot()message.panel_instrument()names the repeated ids in its error “Item ids must be unique; repeated: …”.conjoint_design()stops with “n_tasksmust be one whole number of at least 1, not …” and with the same message forprofiles_per_task. Before,n_tasks = 2.5built two tasks,profiles_per_task = 2.5showed two profiles per task, and a count of zero built an empty design.conjoint_design()stops with “Attribute names must be unique; repeated: …” and, for attributes namedtask,profile,persona_id, orchosen, with “Attribute name … is reserved for the design’s own columns”. Before, both failed later with a tibble error about duplicated column names. It also stops when an attribute has no levels (“must be a vector of at least one level”), a missing or empty level (“has a missing or empty level at position …”), or a repeated level (“repeats the level(s) …”). Before, a repeated level was drawn more often than the others and madeconjoint_amce()stop on a singular design matrix, and anNAlevel was shown as “NA”.The duplicate-profile warning of
conjoint_design()names its cause. “The attribute space is too small for distinct profiles: it holds …” means a task shows more profiles than the attributes can form; “Some tasks contain duplicate profiles because 25 redraws found no distinct one, …” means the redraws ran out in a space that could have supplied them. Before, both cases were reported as a space too small.panel_bias_audit()fillsorder_test_notewheneverorder_effect_pisNA, with the reason no p-value is reported: an open item, an option order that did not vary, fewer than four parsed responses, identical parsed responses, one option shown first in every parsed response, or sparse cells. Before, only sparse cells had a note, and the other cases wereNAin both columns. Whenstats::chisq.test()itself fails, the note records its message and the function warns “The first-option test for item … did not run: …”; before, the failure was dropped without a trace.LLMR::report()prints the note beside “order p = n/a”.
LLMRpanel 0.6.1
CRAN release: 2026-09-12
Corrections replacing 0.6.0, which was never published.
-
item_orderrandomization is gone, andpanel_instrument()refuses it with an explanation: every persona-item pair is an independent request, so no respondent ever sees a questionnaire order, and shuffling a recorded position number claimed an exposure that was never administered.item_positionnow documents the item’s fixed instrument position. - Option-order randomization respects scale structure. Choice options are permuted. A Likert scale has two readable presentations, so it is shown reversed for a random half of responses.
- The submitted grid is the experimental record. A runner contributes responses and provider diagnostics; the assignments it returns are ignored in favor of the ones submitted. Retained provenance grows to request hashes (the default runner now asks LLMR for them), model versions, and durations.
-
panel_benchmark()now rejects a human reference whose probabilities fall outside [0, 1], whose shares miss one, or whose labels were never offered. Conjoint responses are refused, since profiles differ by respondent. An item whose every response failed to parse getsNAshares; zero shares would claim the categories were available and unchosen. -
panel_bias_audit()reportsNAwith a note when chi-square expected counts are sparse, instead of an unreliable p-value. - An administration whose replies come back empty with
finish_reason"length"now warns and namesmax_tokensas the cause. Reasoning models can spend a small budget entirely on hidden reasoning and emit no visible text. -
panel_from_personas()requiresdata; the ANES example must be named. A weight that is NA or negative now stops the call, where it used to be quietly set to zero, and weight columns must be numeric. Weights supplied withoutndraw a warning, since only a sample uses them. -
panel_power()is removed. Its arithmetic treated model-persona dispersion as if it were human outcome variance, which is not a sound basis for planning a human study; a design-sensitivity function with an explicit dispersion source may return later. - Placeholder filling is single-pass, so a substituted value containing braces is left alone.
- The panel print shows a truncated persona preview.
- The Studio’s persona-field default is the demographic fields. Sending all 125 columns put prior attitude items into the prompt, where they leak into the answers; the vignette now executes offline end to end through a deterministic runner, with one live-gated chunk; cross-model comparisons in it reuse the seed so both models face the same assignments.
LLMRpanel 0.6.0
Initial CRAN release.
-
panel_from_margins(),panel_from_data(), andpanel_from_personas()create panels from supplied margins, microdata rows, or persona data frames.as_persona_frame()attaches question and field metadata to a data frame. Reports identify which panel source was used. -
panel_administer()administers every item to every persona. It can randomize item and option order and recordsitem_positionandoption_order. Its classed result stores response rows in$dataand the panel, instrument, benchmark, and token usage in separate fields. Response rows retainresponse_text,response_id,success,model, andprovideras columns. -
panel_batch_submit()submits an administration to a provider’s asynchronous batch API.panel_batch_status()andpanel_batch_fetch()inspect and retrieve the job. Synchronous and batch submission share themax_callsandconfirmgate. -
panel_benchmark()compares response shares with supplied human benchmarks and records benchmark coverage.plot()displays the compared shares. -
panel_bias_audit()reports parse failures and first-option sensitivity. -
conjoint_instrument()creates conjoint choice tasks with profiles randomized independently for each respondent.conjoint_design()returns a classed list with profile and attribute fields, andconjoint_amce()estimates from the recorded respondent-level profiles with standard errors clustered by respondent in a classed result that retains run counts as columns. -
run_panel_studio()provides the panel workflow in an optional Shiny application and can download responses, reports, and benchmark tables. The studio now preserves readable long-form output, presents response shares and diagnostics before technical details, carries administered responses into benchmarking and analysis, supports repeated administrations and conjoint instruments, exposes power and AMCE calculations, permits full ANES persona inspection and field selection, honors shared generation settings, and shows recorded call timing when it is available. Numbered configuration sections can be collapsed while the administration action and run plan remain in view. Persona templates and item wording have editable working defaults. Panel construction, administration, benchmark comparison, power, and AMCE actions are disabled when their known inputs are incomplete, with the unmet requirement shown beside the control. ANES construction separates sampled panels from panels made from selected respondents. Sampled panels disclose replacement sampling above the 100-respondent source size and no longer impose a 500-person GUI ceiling; selected panels require at least one respondent and ignore panel size. A blank shared maximum-output-token field now uses and displays a 512-token package default, while an explicit sidebar value takes precedence. Response text and response labels receive most of the width in display tables, internal identifiers remain available through a column control, and shares, benchmark deviations, and other double columns use concise display-only rounding.
