{ "info": { "author": "dirkmjk", "author_email": "info@dirkmjk.nl", "bugtrack_url": null, "classifiers": [], "description": "[LimeSurvey][limesurvey] is open-source survey software. Using pandas, the limepy package simplifies a number of tasks when working with LimeSurvey data:\n\n- Downloading survey data. This requires that LimeSurvey\u2019s RemoteControl 2 API is enabled, as explained [here][LSRC2].\n- Creating a list of al the questions in the survey, with metadata.\n- Summarising data, e.g. creating value counts for multi-column items such as multiple-choice questions; calculating averages for number arrays; or creating scores for a ranking question.\n- Printing answers to open-ended questions.\n- Printing the answers of an individual respondent.\n\nNote that limepy uses f-strings and therefore requires Python 3.6 or higher.\n\nUse at your own risk and please make sure to check the results.\n\n# How is it different\n\nThere are various python packages for managing the LimeSurvey RemoteControl 2 API. While limepy can help you download survey data, the emphasis is on processing and summarising the data.\n\n# Examples\n\n## Download survey data\n\nYou can download survey data with the RemoteControl 2 API (provided the api is enabled in your LimeSurvey installation).\n\nFor a one-off download, you can of course do this manually. However, you may want to use the api if you want to write a preliminary report based on the first responses, and then automatically update it as new responses come in.\n\n```python\nfrom pathlib import Path\nfrom limepy import download\n\ncsv = download.get_responses(base_url, user_name, password, user_id, sid)\npath = Path('../data/data.csv')\npath.write_text(csv)\n```\n\n## Create Survey object\n\nA Survey object contains the data and metadata of a survey. To create a Survey object, you need:\n\n- A csv containing the survey results. You can download it manually or use the api as described above. Make sure to set heading type to 'code' and reponse type to 'short'.\n- An .lss file containing the survey structure. You can download this manually.\n\n```python\nfrom limepy.wrangle import Survey, Question\nimport pandas as pd\n\ndf = pd.read_csv('../data/data.csv', sep=';')\nmy_structure = open('../data/structure.lss').read()\n\nmy_survey = Survey(df, my_structure)\n```\n\nNote: if you use a merged dataframe (for example, data from various versions of the same questionnaire), you should reset the index before creating a Survey object.\n\n## Get list of questions with metadata\n\n```python\nmy_survey.question_list\n```\n\n## Print results for individual respondent\n\nThe `respondent` method will return a string listing the answers of an individual respondent. You need the respondent\u2019s row index.\n\n```python\nmy_survey.respondent(26)\n```\n\n## Create a readable dataframe\n\nCreate a dataframe with full questions as column names and \u2018long\u2019 responses as values.\n\n```python\nmy_survey.readable_df\n```\n\n## Create a Question object\n\nA Question object can be used to summarise data. To create a Question oject, you need a Survey object and the question id (find it in the index of the question list).\n\n```python\nmy_question = Question(my_survey, 3154)\n```\n\nIf you want to use a subset of the respondents for your analysis (e.g., exclude respondents that do not meet certain criteria, or drop duplicates), the most practical approach is probably to create a subset first and use that to create your Survey object. However, you can also use a mask if you want to create a Question object for a subset of the respondents.\n\n```python\nmy_question = Question(my_survey, 3154, mask=pd.notnull(df.iloc[:, 8]))\n```\n\n## Summarise answers to a question\n\nFor many question types, limepy can summarise the results. \n- In many cases, this will return a dataframe containing value counts (as well as Percent and Valid Percent). \n- In case of a Numerical input question, the output will be a dataframe containing the results of the pandas DataFrame `describe` method. \n- In case of a Numbers array question, the average will be calculated for each option (but you must specify the method, i.e. 'mean' or 'median'). \n- In case of a Ranking question, the result will be a dataframe with scores calculated for each item. \n- If no method has been implemented for a question type, a dataframe will be returned which contains the columns associated with the question.\n\n```python\nmy_question.summary\n```\n\nTo show the metadata associated with a question:\n\n```python\nmy_question.metadata\n```\n\n## Write answers to an open-ended question\n\nThe `write_open_ended` method creates a string listing all the answers to the question. Optionally, you can specify a list of indices of columns that contain background information you want included in the output.\n\n```python\nmy_question.write_open_ended(background_column_indices=[9])\n```\n\nYou can also create a folder and store text files containing the answers to all open-ended questions in the survey.\n\n```python\nfrom pathlib import Path\n\nremove = ' _?:/()'\n\ndef include(row):\n for string in ['free text', 'comment']:\n if string in row.question_type:\n return True\n if row.other == 'Y':\n return True\n return False\n\nfor qid, row in my_survey.question_list.iterrows():\n if include(row):\n question = row.question\n for char in remove:\n question = question.replace(char, ' ')\n question = question[:25]\n path = Path('../data/open_ended') / f'{qid} {question}.md'\n path.write_text(Question(sv, qid).write_open_ended(background_column_indices=[9]))\n```\n\n## Create report as html\n\n```python\ndef add_table(question, question_text=None):\n \"\"\"Add table summarising question\"\"\"\n\n if not question_text:\n question_text = question.question\n html = f\"