expectedparrot / edsl

Design, conduct and analyze results of AI-powered surveys and experiments. Simulate social science and market research with large numbers of AI agents and LLMs.
https://docs.expectedparrot.com
MIT License
194 stars 19 forks source link

Create method for tallying items in QuestionList results #696

Open rbyh opened 5 months ago

rbyh commented 5 months ago

The results tally() method is not working - here for checkbox results:

image
rbyh commented 5 months ago

Modify to work for lists of lists

rbyh commented 5 months ago

Still getting this error after other PR merged

rbyh commented 5 months ago

tally() should allow user to select results based on tally count eg exclude results where tally < 10

johnjosephhorton commented 5 months ago

@rbyh: Can you create a simple, ok-to-share results object on coop + post URL here that has a tally fail? It will help me write agains that.

rbyh commented 5 months ago

Results UUID: '43140db3-17d5-4aae-b702-8a6a9c880c83'

from edsl.questions import QuestionList
from edsl import Agent, Scenario

things = ["birds", "flowers", "toys"]

agents = [Agent(traits = {"favorite_thing":t}) for t in things]

q = QuestionList(
    question_name = "example_tally_list_error",
    question_text = "Name 3 {{ thing }} that are blue."
)

s = [Scenario({"thing":t}) for t in things]

results = q.by(s).by(agents).run()

results.tally("example_tally_list_error")

Error:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[6], line 1
----> 1 results.tally("example_tally_list_error")

File [~/edsl/edsl/results/ResultsExportMixin.py:33](http://localhost:8888/lab/tree/~/edsl/edsl/results/ResultsExportMixin.py#line=32), in ResultsExportMixin._convert_decorator.<locals>.wrapper(self, *args, **kwargs)
     31 """Return the function with the Results object converted to a Dataset object."""
     32 if self.__class__.__name__ == "Results":
---> 33     return func(self.select(), *args, **kwargs)
     34 elif self.__class__.__name__ == "Dataset":
     35     return func(self, *args, **kwargs)

File [~/edsl/edsl/results/ResultsExportMixin.py:515](http://localhost:8888/lab/tree/~/edsl/edsl/results/ResultsExportMixin.py#line=514), in ResultsExportMixin.tally(self, top_n, format, *fields)
    512     if isinstance(value, list):
    513         value = tuple(value)
--> 515 tally = dict(Counter(values))
    516 sorted_tally = dict(sorted(tally.items(), key=lambda item: -item[1]))
    517 if top_n is not None:

File [~/.pyenv/versions/3.11.7/lib/python3.11/collections/__init__.py:599](http://localhost:8888/lab/tree/~/.pyenv/versions/3.11.7/lib/python3.11/collections/__init__.py#line=598), in Counter.__init__(self, iterable, **kwds)
    588 '''Create a new, empty Counter object.  And if given, count elements
    589 from an input iterable.  Or, initialize the count from another mapping
    590 of elements to their counts.
   (...)
    596 
    597 '''
    598 super().__init__()
--> 599 self.update(iterable, **kwds)

File [~/.pyenv/versions/3.11.7/lib/python3.11/collections/__init__.py:690](http://localhost:8888/lab/tree/~/.pyenv/versions/3.11.7/lib/python3.11/collections/__init__.py#line=689), in Counter.update(self, iterable, **kwds)
    688             super().update(iterable)
    689     else:
--> 690         _count_elements(self, iterable)
    691 if kwds:
    692     self.update(kwds)

TypeError: unhashable type: 'list'