├── .editorconfig ├── .github └── workflows │ ├── README.md │ ├── pr-close-signal.yaml │ ├── pr-comment.yaml │ ├── pr-post-remove-branch.yaml │ ├── pr-preflight.yaml │ ├── pr-receive.yaml │ ├── sandpaper-main.yaml │ ├── sandpaper-version.txt │ ├── update-cache.yaml │ └── update-workflows.yaml ├── .gitignore ├── .zenodo.json ├── AUTHORS ├── CITATION ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── config.yaml ├── data └── Moz_SAFI_Survey_Final_results_approved_cleanheaders.csv ├── files ├── setup-data.md ├── setup-openrefine.md ├── setup-overview.md ├── setup-python.md ├── setup-r.md ├── setup-spreadsheet.md └── setup-sql.md ├── index.md ├── instructors └── instructor-notes.md ├── learners ├── data.md ├── reference.md └── setup.Rmd ├── profiles └── learner-profiles.md ├── renv ├── activate.R ├── profile └── profiles │ └── lesson-requirements │ ├── renv.lock │ └── renv │ ├── .gitignore │ └── settings.json ├── setup-python-workshop.Rmd ├── setup-r-workshop.Rmd └── site └── README.md /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | insert_final_newline = true 6 | trim_trailing_whitespace = true 7 | 8 | [*.md] 9 | indent_size = 2 10 | indent_style = space 11 | max_line_length = 100 # Please keep this in sync with bin/lesson_check.py! 12 | 13 | [*.r] 14 | max_line_length = 80 15 | 16 | [*.py] 17 | indent_size = 4 18 | indent_style = space 19 | max_line_length = 79 20 | 21 | [*.sh] 22 | end_of_line = lf 23 | 24 | [Makefile] 25 | indent_style = tab 26 | -------------------------------------------------------------------------------- /.github/workflows/README.md: -------------------------------------------------------------------------------- 1 | # Carpentries Workflows 2 | 3 | This directory contains workflows to be used for Lessons using the {sandpaper} 4 | lesson infrastructure. Two of these workflows require R (`sandpaper-main.yaml` 5 | and `pr-receive.yaml`) and the rest are bots to handle pull request management. 6 | 7 | These workflows will likely change as {sandpaper} evolves, so it is important to 8 | keep them up-to-date. To do this in your lesson you can do the following in your 9 | R console: 10 | 11 | ```r 12 | # Install/Update sandpaper 13 | options(repos = c(carpentries = "https://carpentries.r-universe.dev/", 14 | CRAN = "https://cloud.r-project.org")) 15 | install.packages("sandpaper") 16 | 17 | # update the workflows in your lesson 18 | library("sandpaper") 19 | update_github_workflows() 20 | ``` 21 | 22 | Inside this folder, you will find a file called `sandpaper-version.txt`, which 23 | will contain a version number for sandpaper. This will be used in the future to 24 | alert you if a workflow update is needed. 25 | 26 | What follows are the descriptions of the workflow files: 27 | 28 | ## Deployment 29 | 30 | ### 01 Build and Deploy (sandpaper-main.yaml) 31 | 32 | This is the main driver that will only act on the main branch of the repository. 33 | This workflow does the following: 34 | 35 | 1. checks out the lesson 36 | 2. provisions the following resources 37 | - R 38 | - pandoc 39 | - lesson infrastructure (stored in a cache) 40 | - lesson dependencies if needed (stored in a cache) 41 | 3. builds the lesson via `sandpaper:::ci_deploy()` 42 | 43 | #### Caching 44 | 45 | This workflow has two caches; one cache is for the lesson infrastructure and 46 | the other is for the lesson dependencies if the lesson contains rendered 47 | content. These caches are invalidated by new versions of the infrastructure and 48 | the `renv.lock` file, respectively. If there is a problem with the cache, 49 | manual invaliation is necessary. You will need maintain access to the repository 50 | and you can either go to the actions tab and [click on the caches button to find 51 | and invalidate the failing cache](https://github.blog/changelog/2022-10-20-manage-caches-in-your-actions-workflows-from-web-interface/) 52 | or by setting the `CACHE_VERSION` secret to the current date (which will 53 | invalidate all of the caches). 54 | 55 | ## Updates 56 | 57 | ### Setup Information 58 | 59 | These workflows run on a schedule and at the maintainer's request. Because they 60 | create pull requests that update workflows/require the downstream actions to run, 61 | they need a special repository/organization secret token called 62 | `SANDPAPER_WORKFLOW` and it must have the `public_repo` and `workflow` scope. 63 | 64 | This can be an individual user token, OR it can be a trusted bot account. If you 65 | have a repository in one of the official Carpentries accounts, then you do not 66 | need to worry about this token being present because the Carpentries Core Team 67 | will take care of supplying this token. 68 | 69 | If you want to use your personal account: you can go to 70 | 71 | to create a token. Once you have created your token, you should copy it to your 72 | clipboard and then go to your repository's settings > secrets > actions and 73 | create or edit the `SANDPAPER_WORKFLOW` secret, pasting in the generated token. 74 | 75 | If you do not specify your token correctly, the runs will not fail and they will 76 | give you instructions to provide the token for your repository. 77 | 78 | ### 02 Maintain: Update Workflow Files (update-workflow.yaml) 79 | 80 | The {sandpaper} repository was designed to do as much as possible to separate 81 | the tools from the content. For local builds, this is absolutely true, but 82 | there is a minor issue when it comes to workflow files: they must live inside 83 | the repository. 84 | 85 | This workflow ensures that the workflow files are up-to-date. The way it work is 86 | to download the update-workflows.sh script from GitHub and run it. The script 87 | will do the following: 88 | 89 | 1. check the recorded version of sandpaper against the current version on github 90 | 2. update the files if there is a difference in versions 91 | 92 | After the files are updated, if there are any changes, they are pushed to a 93 | branch called `update/workflows` and a pull request is created. Maintainers are 94 | encouraged to review the changes and accept the pull request if the outputs 95 | are okay. 96 | 97 | This update is run weekly or on demand. 98 | 99 | ### 03 Maintain: Update Package Cache (update-cache.yaml) 100 | 101 | For lessons that have generated content, we use {renv} to ensure that the output 102 | is stable. This is controlled by a single lockfile which documents the packages 103 | needed for the lesson and the version numbers. This workflow is skipped in 104 | lessons that do not have generated content. 105 | 106 | Because the lessons need to remain current with the package ecosystem, it's a 107 | good idea to make sure these packages can be updated periodically. The 108 | update cache workflow will do this by checking for updates, applying them in a 109 | branch called `updates/packages` and creating a pull request with _only the 110 | lockfile changed_. 111 | 112 | From here, the markdown documents will be rebuilt and you can inspect what has 113 | changed based on how the packages have updated. 114 | 115 | ## Pull Request and Review Management 116 | 117 | Because our lessons execute code, pull requests are a secruity risk for any 118 | lesson and thus have security measures associted with them. **Do not merge any 119 | pull requests that do not pass checks and do not have bots commented on them.** 120 | 121 | This series of workflows all go together and are described in the following 122 | diagram and the below sections: 123 | 124 | ![Graph representation of a pull request](https://carpentries.github.io/sandpaper/articles/img/pr-flow.dot.svg) 125 | 126 | ### Pre Flight Pull Request Validation (pr-preflight.yaml) 127 | 128 | This workflow runs every time a pull request is created and its purpose is to 129 | validate that the pull request is okay to run. This means the following things: 130 | 131 | 1. The pull request does not contain modified workflow files 132 | 2. If the pull request contains modified workflow files, it does not contain 133 | modified content files (such as a situation where @carpentries-bot will 134 | make an automated pull request) 135 | 3. The pull request does not contain an invalid commit hash (e.g. from a fork 136 | that was made before a lesson was transitioned from styles to use the 137 | workbench). 138 | 139 | Once the checks are finished, a comment is issued to the pull request, which 140 | will allow maintainers to determine if it is safe to run the 141 | "Receive Pull Request" workflow from new contributors. 142 | 143 | ### Receive Pull Request (pr-receive.yaml) 144 | 145 | **Note of caution:** This workflow runs arbitrary code by anyone who creates a 146 | pull request. GitHub has safeguarded the token used in this workflow to have no 147 | priviledges in the repository, but we have taken precautions to protect against 148 | spoofing. 149 | 150 | This workflow is triggered with every push to a pull request. If this workflow 151 | is already running and a new push is sent to the pull request, the workflow 152 | running from the previous push will be cancelled and a new workflow run will be 153 | started. 154 | 155 | The first step of this workflow is to check if it is valid (e.g. that no 156 | workflow files have been modified). If there are workflow files that have been 157 | modified, a comment is made that indicates that the workflow is not run. If 158 | both a workflow file and lesson content is modified, an error will occurr. 159 | 160 | The second step (if valid) is to build the generated content from the pull 161 | request. This builds the content and uploads three artifacts: 162 | 163 | 1. The pull request number (pr) 164 | 2. A summary of changes after the rendering process (diff) 165 | 3. The rendered files (build) 166 | 167 | Because this workflow builds generated content, it follows the same general 168 | process as the `sandpaper-main` workflow with the same caching mechanisms. 169 | 170 | The artifacts produced are used by the next workflow. 171 | 172 | ### Comment on Pull Request (pr-comment.yaml) 173 | 174 | This workflow is triggered if the `pr-receive.yaml` workflow is successful. 175 | The steps in this workflow are: 176 | 177 | 1. Test if the workflow is valid and comment the validity of the workflow to the 178 | pull request. 179 | 2. If it is valid: create an orphan branch with two commits: the current state 180 | of the repository and the proposed changes. 181 | 3. If it is valid: update the pull request comment with the summary of changes 182 | 183 | Importantly: if the pull request is invalid, the branch is not created so any 184 | malicious code is not published. 185 | 186 | From here, the maintainer can request changes from the author and eventually 187 | either merge or reject the PR. When this happens, if the PR was valid, the 188 | preview branch needs to be deleted. 189 | 190 | ### Send Close PR Signal (pr-close-signal.yaml) 191 | 192 | Triggered any time a pull request is closed. This emits an artifact that is the 193 | pull request number for the next action 194 | 195 | ### Remove Pull Request Branch (pr-post-remove-branch.yaml) 196 | 197 | Tiggered by `pr-close-signal.yaml`. This removes the temporary branch associated with 198 | the pull request (if it was created). 199 | -------------------------------------------------------------------------------- /.github/workflows/pr-close-signal.yaml: -------------------------------------------------------------------------------- 1 | name: "Bot: Send Close Pull Request Signal" 2 | 3 | on: 4 | pull_request: 5 | types: 6 | [closed] 7 | 8 | jobs: 9 | send-close-signal: 10 | name: "Send closing signal" 11 | runs-on: ubuntu-22.04 12 | if: ${{ github.event.action == 'closed' }} 13 | steps: 14 | - name: "Create PRtifact" 15 | run: | 16 | mkdir -p ./pr 17 | printf ${{ github.event.number }} > ./pr/NUM 18 | - name: Upload Diff 19 | uses: actions/upload-artifact@v4 20 | with: 21 | name: pr 22 | path: ./pr 23 | -------------------------------------------------------------------------------- /.github/workflows/pr-comment.yaml: -------------------------------------------------------------------------------- 1 | name: "Bot: Comment on the Pull Request" 2 | 3 | # read-write repo token 4 | # access to secrets 5 | on: 6 | workflow_run: 7 | workflows: ["Receive Pull Request"] 8 | types: 9 | - completed 10 | 11 | concurrency: 12 | group: pr-${{ github.event.workflow_run.pull_requests[0].number }} 13 | cancel-in-progress: true 14 | 15 | 16 | jobs: 17 | # Pull requests are valid if: 18 | # - they match the sha of the workflow run head commit 19 | # - they are open 20 | # - no .github files were committed 21 | test-pr: 22 | name: "Test if pull request is valid" 23 | runs-on: ubuntu-22.04 24 | if: > 25 | github.event.workflow_run.event == 'pull_request' && 26 | github.event.workflow_run.conclusion == 'success' 27 | outputs: 28 | is_valid: ${{ steps.check-pr.outputs.VALID }} 29 | payload: ${{ steps.check-pr.outputs.payload }} 30 | number: ${{ steps.get-pr.outputs.NUM }} 31 | msg: ${{ steps.check-pr.outputs.MSG }} 32 | steps: 33 | - name: 'Download PR artifact' 34 | id: dl 35 | uses: carpentries/actions/download-workflow-artifact@main 36 | with: 37 | run: ${{ github.event.workflow_run.id }} 38 | name: 'pr' 39 | 40 | - name: "Get PR Number" 41 | if: ${{ steps.dl.outputs.success == 'true' }} 42 | id: get-pr 43 | run: | 44 | unzip pr.zip 45 | echo "NUM=$(<./NR)" >> $GITHUB_OUTPUT 46 | 47 | - name: "Fail if PR number was not present" 48 | id: bad-pr 49 | if: ${{ steps.dl.outputs.success != 'true' }} 50 | run: | 51 | echo '::error::A pull request number was not recorded. The pull request that triggered this workflow is likely malicious.' 52 | exit 1 53 | - name: "Get Invalid Hashes File" 54 | id: hash 55 | run: | 56 | echo "json<> $GITHUB_OUTPUT 59 | - name: "Check PR" 60 | id: check-pr 61 | if: ${{ steps.dl.outputs.success == 'true' }} 62 | uses: carpentries/actions/check-valid-pr@main 63 | with: 64 | pr: ${{ steps.get-pr.outputs.NUM }} 65 | sha: ${{ github.event.workflow_run.head_sha }} 66 | headroom: 3 # if it's within the last three commits, we can keep going, because it's likely rapid-fire 67 | invalid: ${{ fromJSON(steps.hash.outputs.json)[github.repository] }} 68 | fail_on_error: true 69 | 70 | # Create an orphan branch on this repository with two commits 71 | # - the current HEAD of the md-outputs branch 72 | # - the output from running the current HEAD of the pull request through 73 | # the md generator 74 | create-branch: 75 | name: "Create Git Branch" 76 | needs: test-pr 77 | runs-on: ubuntu-22.04 78 | if: ${{ needs.test-pr.outputs.is_valid == 'true' }} 79 | env: 80 | NR: ${{ needs.test-pr.outputs.number }} 81 | permissions: 82 | contents: write 83 | steps: 84 | - name: 'Checkout md outputs' 85 | uses: actions/checkout@v4 86 | with: 87 | ref: md-outputs 88 | path: built 89 | fetch-depth: 1 90 | 91 | - name: 'Download built markdown' 92 | id: dl 93 | uses: carpentries/actions/download-workflow-artifact@main 94 | with: 95 | run: ${{ github.event.workflow_run.id }} 96 | name: 'built' 97 | 98 | - if: ${{ steps.dl.outputs.success == 'true' }} 99 | run: unzip built.zip 100 | 101 | - name: "Create orphan and push" 102 | if: ${{ steps.dl.outputs.success == 'true' }} 103 | run: | 104 | cd built/ 105 | git config --local user.email "actions@github.com" 106 | git config --local user.name "GitHub Actions" 107 | CURR_HEAD=$(git rev-parse HEAD) 108 | git checkout --orphan md-outputs-PR-${NR} 109 | git add -A 110 | git commit -m "source commit: ${CURR_HEAD}" 111 | ls -A | grep -v '^.git$' | xargs -I _ rm -r '_' 112 | cd .. 113 | unzip -o -d built built.zip 114 | cd built 115 | git add -A 116 | git commit --allow-empty -m "differences for PR #${NR}" 117 | git push -u --force --set-upstream origin md-outputs-PR-${NR} 118 | 119 | # Comment on the Pull Request with a link to the branch and the diff 120 | comment-pr: 121 | name: "Comment on Pull Request" 122 | needs: [test-pr, create-branch] 123 | runs-on: ubuntu-22.04 124 | if: ${{ needs.test-pr.outputs.is_valid == 'true' }} 125 | env: 126 | NR: ${{ needs.test-pr.outputs.number }} 127 | permissions: 128 | pull-requests: write 129 | steps: 130 | - name: 'Download comment artifact' 131 | id: dl 132 | uses: carpentries/actions/download-workflow-artifact@main 133 | with: 134 | run: ${{ github.event.workflow_run.id }} 135 | name: 'diff' 136 | 137 | - if: ${{ steps.dl.outputs.success == 'true' }} 138 | run: unzip ${{ github.workspace }}/diff.zip 139 | 140 | - name: "Comment on PR" 141 | id: comment-diff 142 | if: ${{ steps.dl.outputs.success == 'true' }} 143 | uses: carpentries/actions/comment-diff@main 144 | with: 145 | pr: ${{ env.NR }} 146 | path: ${{ github.workspace }}/diff.md 147 | 148 | # Comment if the PR is open and matches the SHA, but the workflow files have 149 | # changed 150 | comment-changed-workflow: 151 | name: "Comment if workflow files have changed" 152 | needs: test-pr 153 | runs-on: ubuntu-22.04 154 | if: ${{ always() && needs.test-pr.outputs.is_valid == 'false' }} 155 | env: 156 | NR: ${{ github.event.workflow_run.pull_requests[0].number }} 157 | body: ${{ needs.test-pr.outputs.msg }} 158 | permissions: 159 | pull-requests: write 160 | steps: 161 | - name: 'Check for spoofing' 162 | id: dl 163 | uses: carpentries/actions/download-workflow-artifact@main 164 | with: 165 | run: ${{ github.event.workflow_run.id }} 166 | name: 'built' 167 | 168 | - name: 'Alert if spoofed' 169 | id: spoof 170 | if: ${{ steps.dl.outputs.success == 'true' }} 171 | run: | 172 | echo 'body<> $GITHUB_ENV 173 | echo '' >> $GITHUB_ENV 174 | echo '## :x: DANGER :x:' >> $GITHUB_ENV 175 | echo 'This pull request has modified workflows that created output. Close this now.' >> $GITHUB_ENV 176 | echo '' >> $GITHUB_ENV 177 | echo 'EOF' >> $GITHUB_ENV 178 | 179 | - name: "Comment on PR" 180 | id: comment-diff 181 | uses: carpentries/actions/comment-diff@main 182 | with: 183 | pr: ${{ env.NR }} 184 | body: ${{ env.body }} 185 | -------------------------------------------------------------------------------- /.github/workflows/pr-post-remove-branch.yaml: -------------------------------------------------------------------------------- 1 | name: "Bot: Remove Temporary PR Branch" 2 | 3 | on: 4 | workflow_run: 5 | workflows: ["Bot: Send Close Pull Request Signal"] 6 | types: 7 | - completed 8 | 9 | jobs: 10 | delete: 11 | name: "Delete branch from Pull Request" 12 | runs-on: ubuntu-22.04 13 | if: > 14 | github.event.workflow_run.event == 'pull_request' && 15 | github.event.workflow_run.conclusion == 'success' 16 | permissions: 17 | contents: write 18 | steps: 19 | - name: 'Download artifact' 20 | uses: carpentries/actions/download-workflow-artifact@main 21 | with: 22 | run: ${{ github.event.workflow_run.id }} 23 | name: pr 24 | - name: "Get PR Number" 25 | id: get-pr 26 | run: | 27 | unzip pr.zip 28 | echo "NUM=$(<./NUM)" >> $GITHUB_OUTPUT 29 | - name: 'Remove branch' 30 | uses: carpentries/actions/remove-branch@main 31 | with: 32 | pr: ${{ steps.get-pr.outputs.NUM }} 33 | -------------------------------------------------------------------------------- /.github/workflows/pr-preflight.yaml: -------------------------------------------------------------------------------- 1 | name: "Pull Request Preflight Check" 2 | 3 | on: 4 | pull_request_target: 5 | branches: 6 | ["main"] 7 | types: 8 | ["opened", "synchronize", "reopened"] 9 | 10 | jobs: 11 | test-pr: 12 | name: "Test if pull request is valid" 13 | if: ${{ github.event.action != 'closed' }} 14 | runs-on: ubuntu-22.04 15 | outputs: 16 | is_valid: ${{ steps.check-pr.outputs.VALID }} 17 | permissions: 18 | pull-requests: write 19 | steps: 20 | - name: "Get Invalid Hashes File" 21 | id: hash 22 | run: | 23 | echo "json<> $GITHUB_OUTPUT 26 | - name: "Check PR" 27 | id: check-pr 28 | uses: carpentries/actions/check-valid-pr@main 29 | with: 30 | pr: ${{ github.event.number }} 31 | invalid: ${{ fromJSON(steps.hash.outputs.json)[github.repository] }} 32 | fail_on_error: true 33 | - name: "Comment result of validation" 34 | id: comment-diff 35 | if: ${{ always() }} 36 | uses: carpentries/actions/comment-diff@main 37 | with: 38 | pr: ${{ github.event.number }} 39 | body: ${{ steps.check-pr.outputs.MSG }} 40 | -------------------------------------------------------------------------------- /.github/workflows/pr-receive.yaml: -------------------------------------------------------------------------------- 1 | name: "Receive Pull Request" 2 | 3 | on: 4 | pull_request: 5 | types: 6 | [opened, synchronize, reopened] 7 | 8 | concurrency: 9 | group: ${{ github.ref }} 10 | cancel-in-progress: true 11 | 12 | jobs: 13 | test-pr: 14 | name: "Record PR number" 15 | if: ${{ github.event.action != 'closed' }} 16 | runs-on: ubuntu-22.04 17 | outputs: 18 | is_valid: ${{ steps.check-pr.outputs.VALID }} 19 | steps: 20 | - name: "Record PR number" 21 | id: record 22 | if: ${{ always() }} 23 | run: | 24 | echo ${{ github.event.number }} > ${{ github.workspace }}/NR # 2022-03-02: artifact name fixed to be NR 25 | - name: "Upload PR number" 26 | id: upload 27 | if: ${{ always() }} 28 | uses: actions/upload-artifact@v4 29 | with: 30 | name: pr 31 | path: ${{ github.workspace }}/NR 32 | - name: "Get Invalid Hashes File" 33 | id: hash 34 | run: | 35 | echo "json<> $GITHUB_OUTPUT 38 | - name: "echo output" 39 | run: | 40 | echo "${{ steps.hash.outputs.json }}" 41 | - name: "Check PR" 42 | id: check-pr 43 | uses: carpentries/actions/check-valid-pr@main 44 | with: 45 | pr: ${{ github.event.number }} 46 | invalid: ${{ fromJSON(steps.hash.outputs.json)[github.repository] }} 47 | 48 | build-md-source: 49 | name: "Build markdown source files if valid" 50 | needs: test-pr 51 | runs-on: ubuntu-22.04 52 | if: ${{ needs.test-pr.outputs.is_valid == 'true' }} 53 | env: 54 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 55 | RENV_PATHS_ROOT: ~/.local/share/renv/ 56 | CHIVE: ${{ github.workspace }}/site/chive 57 | PR: ${{ github.workspace }}/site/pr 58 | MD: ${{ github.workspace }}/site/built 59 | steps: 60 | - name: "Check Out Main Branch" 61 | uses: actions/checkout@v4 62 | 63 | - name: "Check Out Staging Branch" 64 | uses: actions/checkout@v4 65 | with: 66 | ref: md-outputs 67 | path: ${{ env.MD }} 68 | 69 | - name: "Set up R" 70 | uses: r-lib/actions/setup-r@v2 71 | with: 72 | use-public-rspm: true 73 | install-r: false 74 | 75 | - name: "Set up Pandoc" 76 | uses: r-lib/actions/setup-pandoc@v2 77 | 78 | - name: "Setup Lesson Engine" 79 | uses: carpentries/actions/setup-sandpaper@main 80 | with: 81 | cache-version: ${{ secrets.CACHE_VERSION }} 82 | 83 | - name: "Setup Package Cache" 84 | uses: carpentries/actions/setup-lesson-deps@main 85 | with: 86 | cache-version: ${{ secrets.CACHE_VERSION }} 87 | 88 | - name: "Validate and Build Markdown" 89 | id: build-site 90 | run: | 91 | sandpaper::package_cache_trigger(TRUE) 92 | sandpaper::validate_lesson(path = '${{ github.workspace }}') 93 | sandpaper:::build_markdown(path = '${{ github.workspace }}', quiet = FALSE) 94 | shell: Rscript {0} 95 | 96 | - name: "Generate Artifacts" 97 | id: generate-artifacts 98 | run: | 99 | sandpaper:::ci_bundle_pr_artifacts( 100 | repo = '${{ github.repository }}', 101 | pr_number = '${{ github.event.number }}', 102 | path_md = '${{ env.MD }}', 103 | path_pr = '${{ env.PR }}', 104 | path_archive = '${{ env.CHIVE }}', 105 | branch = 'md-outputs' 106 | ) 107 | shell: Rscript {0} 108 | 109 | - name: "Upload PR" 110 | uses: actions/upload-artifact@v4 111 | with: 112 | name: pr 113 | path: ${{ env.PR }} 114 | overwrite: true 115 | 116 | - name: "Upload Diff" 117 | uses: actions/upload-artifact@v4 118 | with: 119 | name: diff 120 | path: ${{ env.CHIVE }} 121 | retention-days: 1 122 | 123 | - name: "Upload Build" 124 | uses: actions/upload-artifact@v4 125 | with: 126 | name: built 127 | path: ${{ env.MD }} 128 | retention-days: 1 129 | 130 | - name: "Teardown" 131 | run: sandpaper::reset_site() 132 | shell: Rscript {0} 133 | -------------------------------------------------------------------------------- /.github/workflows/sandpaper-main.yaml: -------------------------------------------------------------------------------- 1 | name: "01 Build and Deploy Site" 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - master 8 | schedule: 9 | - cron: '0 0 * * 2' 10 | workflow_dispatch: 11 | inputs: 12 | name: 13 | description: 'Who triggered this build?' 14 | required: true 15 | default: 'Maintainer (via GitHub)' 16 | reset: 17 | description: 'Reset cached markdown files' 18 | required: false 19 | default: false 20 | type: boolean 21 | jobs: 22 | full-build: 23 | name: "Build Full Site" 24 | 25 | # 2024-10-01: ubuntu-latest is now 24.04 and R is not installed by default in the runner image 26 | # pin to 22.04 for now 27 | runs-on: ubuntu-22.04 28 | permissions: 29 | checks: write 30 | contents: write 31 | pages: write 32 | env: 33 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 34 | RENV_PATHS_ROOT: ~/.local/share/renv/ 35 | steps: 36 | 37 | - name: "Checkout Lesson" 38 | uses: actions/checkout@v4 39 | 40 | - name: "Set up R" 41 | uses: r-lib/actions/setup-r@v2 42 | with: 43 | use-public-rspm: true 44 | install-r: false 45 | 46 | - name: "Set up Pandoc" 47 | uses: r-lib/actions/setup-pandoc@v2 48 | 49 | - name: "Setup Lesson Engine" 50 | uses: carpentries/actions/setup-sandpaper@main 51 | with: 52 | cache-version: ${{ secrets.CACHE_VERSION }} 53 | 54 | - name: "Setup Package Cache" 55 | uses: carpentries/actions/setup-lesson-deps@main 56 | with: 57 | cache-version: ${{ secrets.CACHE_VERSION }} 58 | 59 | - name: "Deploy Site" 60 | run: | 61 | reset <- "${{ github.event.inputs.reset }}" == "true" 62 | sandpaper::package_cache_trigger(TRUE) 63 | sandpaper:::ci_deploy(reset = reset) 64 | shell: Rscript {0} 65 | -------------------------------------------------------------------------------- /.github/workflows/sandpaper-version.txt: -------------------------------------------------------------------------------- 1 | 0.16.12 2 | -------------------------------------------------------------------------------- /.github/workflows/update-cache.yaml: -------------------------------------------------------------------------------- 1 | name: "03 Maintain: Update Package Cache" 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | name: 7 | description: 'Who triggered this build (enter github username to tag yourself)?' 8 | required: true 9 | default: 'monthly run' 10 | schedule: 11 | # Run every tuesday 12 | - cron: '0 0 * * 2' 13 | 14 | jobs: 15 | preflight: 16 | name: "Preflight Check" 17 | runs-on: ubuntu-22.04 18 | outputs: 19 | ok: ${{ steps.check.outputs.ok }} 20 | steps: 21 | - id: check 22 | run: | 23 | if [[ ${{ github.event_name }} == 'workflow_dispatch' ]]; then 24 | echo "ok=true" >> $GITHUB_OUTPUT 25 | echo "Running on request" 26 | # using single brackets here to avoid 08 being interpreted as octal 27 | # https://github.com/carpentries/sandpaper/issues/250 28 | elif [ `date +%d` -le 7 ]; then 29 | # If the Tuesday lands in the first week of the month, run it 30 | echo "ok=true" >> $GITHUB_OUTPUT 31 | echo "Running on schedule" 32 | else 33 | echo "ok=false" >> $GITHUB_OUTPUT 34 | echo "Not Running Today" 35 | fi 36 | 37 | check_renv: 38 | name: "Check if We Need {renv}" 39 | runs-on: ubuntu-22.04 40 | needs: preflight 41 | if: ${{ needs.preflight.outputs.ok == 'true'}} 42 | outputs: 43 | needed: ${{ steps.renv.outputs.exists }} 44 | steps: 45 | - name: "Checkout Lesson" 46 | uses: actions/checkout@v4 47 | - id: renv 48 | run: | 49 | if [[ -d renv ]]; then 50 | echo "exists=true" >> $GITHUB_OUTPUT 51 | fi 52 | 53 | check_token: 54 | name: "Check SANDPAPER_WORKFLOW token" 55 | runs-on: ubuntu-22.04 56 | needs: check_renv 57 | if: ${{ needs.check_renv.outputs.needed == 'true' }} 58 | outputs: 59 | workflow: ${{ steps.validate.outputs.wf }} 60 | repo: ${{ steps.validate.outputs.repo }} 61 | steps: 62 | - name: "validate token" 63 | id: validate 64 | uses: carpentries/actions/check-valid-credentials@main 65 | with: 66 | token: ${{ secrets.SANDPAPER_WORKFLOW }} 67 | 68 | update_cache: 69 | name: "Update Package Cache" 70 | needs: check_token 71 | if: ${{ needs.check_token.outputs.repo== 'true' }} 72 | runs-on: ubuntu-22.04 73 | env: 74 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 75 | RENV_PATHS_ROOT: ~/.local/share/renv/ 76 | steps: 77 | 78 | - name: "Checkout Lesson" 79 | uses: actions/checkout@v4 80 | 81 | - name: "Set up R" 82 | uses: r-lib/actions/setup-r@v2 83 | with: 84 | use-public-rspm: true 85 | install-r: false 86 | 87 | - name: "Update {renv} deps and determine if a PR is needed" 88 | id: update 89 | uses: carpentries/actions/update-lockfile@main 90 | with: 91 | cache-version: ${{ secrets.CACHE_VERSION }} 92 | 93 | - name: Create Pull Request 94 | id: cpr 95 | if: ${{ steps.update.outputs.n > 0 }} 96 | uses: carpentries/create-pull-request@main 97 | with: 98 | token: ${{ secrets.SANDPAPER_WORKFLOW }} 99 | delete-branch: true 100 | branch: "update/packages" 101 | commit-message: "[actions] update ${{ steps.update.outputs.n }} packages" 102 | title: "Update ${{ steps.update.outputs.n }} packages" 103 | body: | 104 | :robot: This is an automated build 105 | 106 | This will update ${{ steps.update.outputs.n }} packages in your lesson with the following versions: 107 | 108 | ``` 109 | ${{ steps.update.outputs.report }} 110 | ``` 111 | 112 | :stopwatch: In a few minutes, a comment will appear that will show you how the output has changed based on these updates. 113 | 114 | If you want to inspect these changes locally, you can use the following code to check out a new branch: 115 | 116 | ```bash 117 | git fetch origin update/packages 118 | git checkout update/packages 119 | ``` 120 | 121 | - Auto-generated by [create-pull-request][1] on ${{ steps.update.outputs.date }} 122 | 123 | [1]: https://github.com/carpentries/create-pull-request/tree/main 124 | labels: "type: package cache" 125 | draft: false 126 | -------------------------------------------------------------------------------- /.github/workflows/update-workflows.yaml: -------------------------------------------------------------------------------- 1 | name: "02 Maintain: Update Workflow Files" 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | name: 7 | description: 'Who triggered this build (enter github username to tag yourself)?' 8 | required: true 9 | default: 'weekly run' 10 | clean: 11 | description: 'Workflow files/file extensions to clean (no wildcards, enter "" for none)' 12 | required: false 13 | default: '.yaml' 14 | schedule: 15 | # Run every Tuesday 16 | - cron: '0 0 * * 2' 17 | 18 | jobs: 19 | check_token: 20 | name: "Check SANDPAPER_WORKFLOW token" 21 | runs-on: ubuntu-22.04 22 | outputs: 23 | workflow: ${{ steps.validate.outputs.wf }} 24 | repo: ${{ steps.validate.outputs.repo }} 25 | steps: 26 | - name: "validate token" 27 | id: validate 28 | uses: carpentries/actions/check-valid-credentials@main 29 | with: 30 | token: ${{ secrets.SANDPAPER_WORKFLOW }} 31 | 32 | update_workflow: 33 | name: "Update Workflow" 34 | runs-on: ubuntu-22.04 35 | needs: check_token 36 | if: ${{ needs.check_token.outputs.workflow == 'true' }} 37 | steps: 38 | - name: "Checkout Repository" 39 | uses: actions/checkout@v4 40 | 41 | - name: Update Workflows 42 | id: update 43 | uses: carpentries/actions/update-workflows@main 44 | with: 45 | clean: ${{ github.event.inputs.clean }} 46 | 47 | - name: Create Pull Request 48 | id: cpr 49 | if: "${{ steps.update.outputs.new }}" 50 | uses: carpentries/create-pull-request@main 51 | with: 52 | token: ${{ secrets.SANDPAPER_WORKFLOW }} 53 | delete-branch: true 54 | branch: "update/workflows" 55 | commit-message: "[actions] update sandpaper workflow to version ${{ steps.update.outputs.new }}" 56 | title: "Update Workflows to Version ${{ steps.update.outputs.new }}" 57 | body: | 58 | :robot: This is an automated build 59 | 60 | Update Workflows from sandpaper version ${{ steps.update.outputs.old }} -> ${{ steps.update.outputs.new }} 61 | 62 | - Auto-generated by [create-pull-request][1] on ${{ steps.update.outputs.date }} 63 | 64 | [1]: https://github.com/carpentries/create-pull-request/tree/main 65 | labels: "type: template and tools" 66 | draft: false 67 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # sandpaper files 2 | episodes/*html 3 | site/* 4 | !site/README.md 5 | 6 | # History files 7 | .Rhistory 8 | .Rapp.history 9 | # Session Data files 10 | .RData 11 | # User-specific files 12 | .Ruserdata 13 | # Example code in package build process 14 | *-Ex.R 15 | # Output files from R CMD build 16 | /*.tar.gz 17 | # Output files from R CMD check 18 | /*.Rcheck/ 19 | # RStudio files 20 | .Rproj.user/ 21 | # produced vignettes 22 | vignettes/*.html 23 | vignettes/*.pdf 24 | # OAuth2 token, see https://github.com/hadley/httr/releases/tag/v0.3 25 | .httr-oauth 26 | # knitr and R markdown default cache directories 27 | *_cache/ 28 | /cache/ 29 | # Temporary files created by R markdown 30 | *.utf8.md 31 | *.knit.md 32 | # R Environment Variables 33 | .Renviron 34 | # pkgdown site 35 | docs/ 36 | # translation temp files 37 | po/*~ 38 | # renv detritus 39 | renv/sandbox/ 40 | *.pyc 41 | *~ 42 | .DS_Store 43 | .ipynb_checkpoints 44 | .sass-cache 45 | .jekyll-cache/ 46 | __pycache__ 47 | _site 48 | .Rproj.user 49 | .bundle/ 50 | .vendor/ 51 | .docker-vendor/ 52 | Gemfile.lock 53 | -------------------------------------------------------------------------------- /.zenodo.json: -------------------------------------------------------------------------------- 1 | { 2 | "contributors": [ 3 | { 4 | "type": "Editor", 5 | "name": "Johanna Bayer" 6 | }, 7 | { 8 | "type": "Editor", 9 | "name": "Jean Baptiste Fankam Fankam", 10 | "orcid": "0000-0003-0389-5404" 11 | }, 12 | { 13 | "type": "Editor", 14 | "name": "Jesse Sadler" 15 | } 16 | ], 17 | "creators": [ 18 | { 19 | "name": "Erin Alison Becker", 20 | "orcid": "0000-0002-6832-0233" 21 | }, 22 | { 23 | "name": "Ben Companjen" 24 | }, 25 | { 26 | "name": "Christopher Prener" 27 | }, 28 | { 29 | "name": "Jean Baptiste Fankam Fankam", 30 | "orcid": "0000-0003-0389-5404" 31 | }, 32 | { 33 | "name": "Johanna Bayer" 34 | }, 35 | { 36 | "name": "Johanna Bayer" 37 | }, 38 | { 39 | "name": "Katrin Leinweber", 40 | "orcid": "0000-0001-5135-5758" 41 | }, 42 | { 43 | "name": "Maneesha Sane" 44 | }, 45 | { 46 | "name": "Saber Soleymani", 47 | "orcid": "0000-0002-0771-4319" 48 | }, 49 | { 50 | "name": "ThorkellMoon" 51 | }, 52 | { 53 | "name": "Laura Josephine Botzet" 54 | } 55 | ], 56 | "license": { 57 | "id": "CC-BY-4.0" 58 | } 59 | } -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | FIXME: list authors' names and email addresses. 2 | -------------------------------------------------------------------------------- /CITATION: -------------------------------------------------------------------------------- 1 | FIXME: describe how to cite this lesson. 2 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Contributor Code of Conduct" 3 | --- 4 | 5 | As contributors and maintainers of this project, 6 | we pledge to follow the [The Carpentries Code of Conduct][coc]. 7 | 8 | Instances of abusive, harassing, or otherwise unacceptable behavior 9 | may be reported by following our [reporting guidelines][coc-reporting]. 10 | 11 | [coc]: https://docs.carpentries.org/topic_folders/policies/code-of-conduct.html 12 | [coc-reporting]: https://docs.carpentries.org/topic_folders/policies/incident-reporting.html 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing 2 | 3 | [The Carpentries][cp-site] ([Software Carpentry][swc-site], [Data 4 | Carpentry][dc-site], and [Library Carpentry][lc-site]) are open source 5 | projects, and we welcome contributions of all kinds: new lessons, fixes to 6 | existing material, bug reports, and reviews of proposed changes are all 7 | welcome. 8 | 9 | ### Contributor Agreement 10 | 11 | By contributing, you agree that we may redistribute your work under [our 12 | license](LICENSE.md). In exchange, we will address your issues and/or assess 13 | your change proposal as promptly as we can, and help you become a member of our 14 | community. Everyone involved in [The Carpentries][cp-site] agrees to abide by 15 | our [code of conduct](CODE_OF_CONDUCT.md). 16 | 17 | ### How to Contribute 18 | 19 | The easiest way to get started is to file an issue to tell us about a spelling 20 | mistake, some awkward wording, or a factual error. This is a good way to 21 | introduce yourself and to meet some of our community members. 22 | 23 | 1. If you do not have a [GitHub][github] account, you can [send us comments by 24 | email][contact]. However, we will be able to respond more quickly if you use 25 | one of the other methods described below. 26 | 27 | 2. If you have a [GitHub][github] account, or are willing to [create 28 | one][github-join], but do not know how to use Git, you can report problems 29 | or suggest improvements by [creating an issue][repo-issues]. This allows us 30 | to assign the item to someone and to respond to it in a threaded discussion. 31 | 32 | 3. If you are comfortable with Git, and would like to add or change material, 33 | you can submit a pull request (PR). Instructions for doing this are 34 | [included below](#using-github). For inspiration about changes that need to 35 | be made, check out the [list of open issues][issues] across the Carpentries. 36 | 37 | Note: if you want to build the website locally, please refer to [The Workbench 38 | documentation][template-doc]. 39 | 40 | ### Where to Contribute 41 | 42 | 1. If you wish to change this lesson, add issues and pull requests here. 43 | 2. If you wish to change the template used for workshop websites, please refer 44 | to [The Workbench documentation][template-doc]. 45 | 46 | ### What to Contribute 47 | 48 | There are many ways to contribute, from writing new exercises and improving 49 | existing ones to updating or filling in the documentation and submitting [bug 50 | reports][issues] about things that do not work, are not clear, or are missing. 51 | If you are looking for ideas, please see [the list of issues for this 52 | repository][repo-issues], or the issues for [Data Carpentry][dc-issues], 53 | [Library Carpentry][lc-issues], and [Software Carpentry][swc-issues] projects. 54 | 55 | Comments on issues and reviews of pull requests are just as welcome: we are 56 | smarter together than we are on our own. **Reviews from novices and newcomers 57 | are particularly valuable**: it's easy for people who have been using these 58 | lessons for a while to forget how impenetrable some of this material can be, so 59 | fresh eyes are always welcome. 60 | 61 | ### What *Not* to Contribute 62 | 63 | Our lessons already contain more material than we can cover in a typical 64 | workshop, so we are usually *not* looking for more concepts or tools to add to 65 | them. As a rule, if you want to introduce a new idea, you must (a) estimate how 66 | long it will take to teach and (b) explain what you would take out to make room 67 | for it. The first encourages contributors to be honest about requirements; the 68 | second, to think hard about priorities. 69 | 70 | We are also not looking for exercises or other material that only run on one 71 | platform. Our workshops typically contain a mixture of Windows, macOS, and 72 | Linux users; in order to be usable, our lessons must run equally well on all 73 | three. 74 | 75 | ### Using GitHub 76 | 77 | If you choose to contribute via GitHub, you may want to look at [How to 78 | Contribute to an Open Source Project on GitHub][how-contribute]. In brief, we 79 | use [GitHub flow][github-flow] to manage changes: 80 | 81 | 1. Create a new branch in your desktop copy of this repository for each 82 | significant change. 83 | 2. Commit the change in that branch. 84 | 3. Push that branch to your fork of this repository on GitHub. 85 | 4. Submit a pull request from that branch to the [upstream repository][repo]. 86 | 5. If you receive feedback, make changes on your desktop and push to your 87 | branch on GitHub: the pull request will update automatically. 88 | 89 | NB: The published copy of the lesson is usually in the `main` branch. 90 | 91 | Each lesson has a team of maintainers who review issues and pull requests or 92 | encourage others to do so. The maintainers are community volunteers, and have 93 | final say over what gets merged into the lesson. 94 | 95 | ### Other Resources 96 | 97 | The Carpentries is a global organisation with volunteers and learners all over 98 | the world. We share values of inclusivity and a passion for sharing knowledge, 99 | teaching and learning. There are several ways to connect with The Carpentries 100 | community listed at [https://carpentries.org/connect/](https://carpentries.org/connect/) including via social 101 | media, slack, newsletters, and email lists. You can also [reach us by 102 | email][contact]. 103 | 104 | [cp-site]: https://carpentries.org/ 105 | [swc-site]: https://software-carpentry.org/ 106 | [dc-site]: https://datacarpentry.org/ 107 | [lc-site]: https://librarycarpentry.org/ 108 | [github]: https://github.com 109 | [contact]: mailto:team@carpentries.org 110 | [github-join]: https://github.com/join 111 | [repo-issues]: https://github.com/datacarpentry/socialsci-workshop/issues 112 | [issues]: https://carpentries.org/help-wanted-issues/ 113 | [template-doc]: https://carpentries.github.io/workbench/ 114 | [dc-issues]: https://github.com/issues?q=user%3Adatacarpentry 115 | [lc-issues]: https://github.com/issues?q=user%3ALibraryCarpentry 116 | [swc-issues]: https://github.com/issues?q=user%3Aswcarpentry 117 | [how-contribute]: https://egghead.io/courses/how-to-contribute-to-an-open-source-project-on-github 118 | [github-flow]: https://guides.github.com/introduction/flow/ 119 | [repo]: https://github.com/datacarpentry/socialsci-workshop 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Licenses" 3 | --- 4 | 5 | ## Instructional Material 6 | 7 | All Carpentries (Software Carpentry, Data Carpentry, and Library Carpentry) 8 | instructional material is made available under the [Creative Commons 9 | Attribution license][cc-by-human]. The following is a human-readable summary of 10 | (and not a substitute for) the [full legal text of the CC BY 4.0 11 | license][cc-by-legal]. 12 | 13 | You are free: 14 | 15 | - to **Share**\---copy and redistribute the material in any medium or format 16 | - to **Adapt**\---remix, transform, and build upon the material 17 | 18 | for any purpose, even commercially. 19 | 20 | The licensor cannot revoke these freedoms as long as you follow the license 21 | terms. 22 | 23 | Under the following terms: 24 | 25 | - **Attribution**\---You must give appropriate credit (mentioning that your work 26 | is derived from work that is Copyright (c) The Carpentries and, where 27 | practical, linking to [https://carpentries.org/](https://carpentries.org/)), provide a [link to the 28 | license][cc-by-human], and indicate if changes were made. You may do so in 29 | any reasonable manner, but not in any way that suggests the licensor endorses 30 | you or your use. 31 | 32 | - **No additional restrictions**\---You may not apply legal terms or 33 | technological measures that legally restrict others from doing anything the 34 | license permits. With the understanding that: 35 | 36 | Notices: 37 | 38 | - You do not have to comply with the license for elements of the material in 39 | the public domain or where your use is permitted by an applicable exception 40 | or limitation. 41 | - No warranties are given. The license may not give you all of the permissions 42 | necessary for your intended use. For example, other rights such as publicity, 43 | privacy, or moral rights may limit how you use the material. 44 | 45 | ## Software 46 | 47 | Except where otherwise noted, the example programs and other software provided 48 | by The Carpentries are made available under the [OSI][osi]\-approved [MIT 49 | license][mit-license]. 50 | 51 | Permission is hereby granted, free of charge, to any person obtaining a copy of 52 | this software and associated documentation files (the "Software"), to deal in 53 | the Software without restriction, including without limitation the rights to 54 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 55 | of the Software, and to permit persons to whom the Software is furnished to do 56 | so, subject to the following conditions: 57 | 58 | The above copyright notice and this permission notice shall be included in all 59 | copies or substantial portions of the Software. 60 | 61 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 62 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 63 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 64 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 65 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 66 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 67 | SOFTWARE. 68 | 69 | ## Trademark 70 | 71 | "The Carpentries", "Software Carpentry", "Data Carpentry", and "Library 72 | Carpentry" and their respective logos are registered trademarks of 73 | [The Carpentries, Inc.][carpentries]. 74 | 75 | [cc-by-human]: https://creativecommons.org/licenses/by/4.0/ 76 | [cc-by-legal]: https://creativecommons.org/licenses/by/4.0/legalcode 77 | [mit-license]: https://opensource.org/licenses/mit-license.html 78 | [carpentries]: https://carpentries.org 79 | [osi]: https://opensource.org 80 | 81 | 82 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![DOI](https://zenodo.org/badge/92422998.svg)](https://zenodo.org/badge/latestdoi/92422998) 2 | 3 | # Social Sciences Workshop 4 | 5 | A workshop for teaching data management and analysis for social science research including best practices for data organization,reproducible data cleaning, , and data analysis and visualization. Please see [https://datacarpentry.org/socialsci-workshop/](https://datacarpentry.org/socialsci-workshop/) for a rendered version of this material, [the lesson template documentation](https://carpentries.github.io/lesson-example/) for instructions on formatting, building, and submitting material, or run make in this directory for a list of helpful commands. 6 | 7 | ## Code of Conduct 8 | 9 | All participants should agree to abide by the [Carpentries Code of Conduct](https://docs.carpentries.org/topic_folders/policies/code-of-conduct.html). 10 | 11 | ## Authors 12 | 13 | The Social Sciences workshop overview is authored and maintained by the [Curriculum Advisory Committee](https://www.datacarpentry.org/lesson-leadership/#curriculum-advisors---social-sciences). 14 | 15 | ## Citation 16 | 17 | Please cite as: 18 | 19 | Data Carpentry Social Sciences Workshop. May 2018. 20 | 21 | 22 | -------------------------------------------------------------------------------- /config.yaml: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------ 2 | # Values for this lesson. 3 | #------------------------------------------------------------ 4 | 5 | # Which carpentry is this (swc, dc, lc, or cp)? 6 | # swc: Software Carpentry 7 | # dc: Data Carpentry 8 | # lc: Library Carpentry 9 | # cp: Carpentries (to use for instructor training for instance) 10 | # incubator: The Carpentries Incubator 11 | carpentry: 'dc' 12 | 13 | # Overall title for pages. 14 | title: 'Social Science Workshop Overview' 15 | 16 | # Date the lesson was created (YYYY-MM-DD, this is empty by default) 17 | created: '2017-05-25' 18 | 19 | # Comma-separated list of keywords for the lesson 20 | keywords: 'software, data, lesson, The Carpentries' # FIXME 21 | 22 | # Life cycle stage of the lesson 23 | # possible values: pre-alpha, alpha, beta, stable 24 | life_cycle: 'stable' 25 | 26 | # License of the lesson 27 | license: 'CC-BY 4.0' 28 | 29 | # Link to the source repository for this lesson 30 | source: 'https://github.com/datacarpentry/socialsci-workshop' 31 | 32 | # Default branch of your lesson 33 | branch: 'main' 34 | 35 | # Who to contact if there are any issues 36 | contact: 'team@carpentries.org' 37 | 38 | # Navigation ------------------------------------------------ 39 | # 40 | # Use the following menu items to specify the order of 41 | # individual pages in each dropdown section. Leave blank to 42 | # include all pages in the folder. 43 | # 44 | # Example ------------- 45 | # 46 | # episodes: 47 | # - introduction.md 48 | # - first-steps.md 49 | # 50 | # learners: 51 | # - setup.md 52 | # 53 | # instructors: 54 | # - instructor-notes.md 55 | # 56 | # profiles: 57 | # - one-learner.md 58 | # - another-learner.md 59 | 60 | # Order of episodes in your lesson 61 | episodes: 62 | - introduction.Rmd 63 | 64 | # Information for Learners 65 | learners: 66 | 67 | # Information for Instructors 68 | instructors: 69 | 70 | # Learner Profiles 71 | profiles: 72 | 73 | # Customisation --------------------------------------------- 74 | # 75 | # This space below is where custom yaml items (e.g. pinning 76 | # sandpaper and varnish versions) should live 77 | 78 | 79 | url: 'https://datacarpentry.github.io/socialsci-workshop' 80 | analytics: 'carpentries' 81 | lang: 'en' 82 | overview: true 83 | -------------------------------------------------------------------------------- /data/Moz_SAFI_Survey_Final_results_approved_cleanheaders.csv: -------------------------------------------------------------------------------- 1 | interview_date,quest_no,start,end,province,district,ward,village,years_farm,agr_assoc,no_membrs,_members_count,remittance_money,years_liv,parents_liv,sp_parents_liv,grand_liv,sp_grand_liv,respondent_roof_type,respondent_wall_type,respondent_wall_type_other,respondent_floor_type,window_type,buildings_in_compound,rooms,other_buildings,no_plots,plots_count,water_use,no_group_count,yes_group_count,no_enough_water,months_no_water,period_use,exper_other,other_meth,res_change,memb_assoc,resp_assoc,fees_water,affect_conflicts,need_money,money_source,money_source_other,crops_contr,emply_lab,du_labour,liv_owned,liv_owned_other,liv_count,poultry,du_look_aftr_cows,items_owned,items_owned_other,no_meals,months_lack_food,no_food_mitigation,gps_Latitude,gps_Longitude,gps_Altitude,gps_Accuracy,instanceID 2 | 17-Nov-16,1,2017-03-23T09:49:57.000Z,2017-04-02T17:29:08.000Z,Manica,Manica,Bandula,God,11,no,3,3,no,4,no,yes,no,yes,grass,muddaub,NULL,earth,no,1,1,no,2,2,no,2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,no,no,['poultry'],NULL,1,yes,no,['bicycle' ; 'television' ; 'solar_panel' ; 'table'],NULL,2,['Jan'],['na' ; 'rely_less_food' ; 'reduce_meals' ; 'day_night_hungry'],-19.11225943,33.48345609,698,14,uuid:ec241f2c-0609-46ed-b5e8-fe575f6cefef 3 | 17-Nov-16,1,2017-04-02T09:48:16.000Z,2017-04-02T17:26:19.000Z,Manica,Manica,Bandula,God,2,yes,7,7,no,9,yes,yes,yes,yes,grass,muddaub,NULL,earth,no,1,1,no,3,3,yes,NULL,3,yes,['Aug' ; 'Sept'],2,yes,no,NULL,yes,no,no,once,no,NULL,NULL,more_half,yes,no,['oxen' ; 'cows' ; 'goats'],NULL,3,yes,no,['cow_cart' ; 'bicycle' ; 'radio' ; 'cow_plough' ; 'solar_panel' ; 'solar_torch' ; 'table' ; 'mobile_phone'],NULL,2,['Jan' ; 'Sept' ; 'Oct' ; 'Nov' ; 'Dec'],['na' ; 'reduce_meals' ; 'restrict_adults' ; 'borrow_food' ; 'seek_government'],-19.11247712,33.48341568,690,19,uuid:099de9c9-3e5e-427b-8452-26250e840d6e 4 | 17-Nov-16,3,2017-04-02T14:35:26.000Z,2017-04-02T17:26:53.000Z,Manica,Manica,Bandula,God,40,no,10,10,no,15,no,no,no,no,mabatisloping,burntbricks,NULL,cement,yes,1,1,no,1,1,no,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,no,yes,['none'],NULL,1,yes,no,['solar_torch'],NULL,2,['Jan' ; 'Feb' ; 'Mar' ; 'Oct' ; 'Nov' ; 'Dec'],['na' ; 'restrict_adults' ; 'lab_ex_food'],-19.1121076,33.48344998,674,13,uuid:193d7daf-9582-409b-bf09-027dd36f9007 5 | 17-Nov-16,4,2017-04-02T14:55:18.000Z,2017-04-02T17:27:16.000Z,Manica,Manica,Bandula,God,6,no,7,7,no,6,no,no,no,no,mabatisloping,burntbricks,NULL,earth,no,1,1,no,3,3,no,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,no,yes,['oxen' ; 'cows'],NULL,2,yes,no,['bicycle' ; 'radio' ; 'cow_plough' ; 'solar_panel' ; 'mobile_phone'],NULL,2,['Sept' ; 'Oct' ; 'Nov' ; 'Dec'],['na' ; 'reduce_meals' ; 'restrict_adults' ; 'lab_ex_food'],-19.11222901,33.48342395,679,5,uuid:148d1105-778a-4755-aa71-281eadd4a973 6 | 17-Nov-16,5,2017-04-02T15:10:35.000Z,2017-04-02T17:27:35.000Z,Manica,Manica,Bandula,God,18,no,7,7,no,40,yes,no,yes,no,grass,burntbricks,NULL,earth,no,1,1,no,2,2,no,2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,no,no,['oxen' ; 'cows' ; 'goats' ; 'poultry'],NULL,4,yes,no,['motorcyle' ; 'radio' ; 'cow_plough' ; 'mobile_phone'],NULL,2,['Aug' ; 'Sept' ; 'Oct' ; 'Nov'],['na' ; 'go_forest' ; 'migrate'],-19.11221722,33.48342524,689,10,uuid:2c867811-9696-4966-9866-f35c3e97d02d 7 | 17-Nov-16,6,2017-04-02T15:27:25.000Z,2017-04-02T17:28:02.000Z,Manica,Manica,Bandula,God,3,no,3,3,no,3,no,no,no,no,grass,muddaub,NULL,earth,no,1,1,no,1,1,no,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,no,yes,['none'],NULL,1,no,no,NULL,NULL,2,['Aug' ; 'Sept' ; 'Oct'],['borrow_food' ; 'lab_ex_food' ; 'seek_government'],-19.1121959,33.48339187,692,12,uuid:daa56c91-c8e3-44c3-a663-af6a49a2ca70 8 | 17-Nov-16,7,2017-04-02T15:38:01.000Z,2017-04-02T17:28:19.000Z,Manica,Manica,Bandula,God,20,no,6,6,no,38,yes,no,yes,no,grass,muddaub,NULL,earth,no,1,1,yes,4,4,yes,NULL,4,yes,['Aug' ; 'Sept' ; 'Oct'],10,yes,no,NULL,no,NULL,no,never,no,NULL,NULL,more_half,no,no,['oxen'],NULL,1,no,no,['motorcyle' ; 'cow_plough'],NULL,3,['Nov'],['lab_ex_food'],-19.11221904,33.48336498,709,11,uuid:ae20a58d-56f4-43d7-bafa-e7963d850844 9 | 16-Nov-16,8,2017-04-02T15:59:52.000Z,2017-04-02T17:28:39.000Z,Manica,Manica,Manica,Chirodzo,16,yes,12,12,no,70,yes,yes,yes,yes,mabatisloping,burntbricks,NULL,cement,no,2,3,yes,2,2,yes,NULL,2,yes,['Sept' ; 'Oct'],10,yes,no,NULL,yes,yes,no,never,no,NULL,NULL,abt_half,yes,no,['oxen' ; 'goats'],NULL,2,yes,no,['motorcyle' ; 'bicycle' ; 'television' ; 'radio' ; 'cow_plough' ; 'solar_panel' ; 'solar_torch' ; 'table' ; 'fridge'],NULL,2,['Jan'],['rely_less_food' ; 'limit_variety' ; 'reduce_meals' ; 'restrict_adults' ; 'borrow_food'],-19.11215963,33.48341914,700,9,uuid:d6cee930-7be1-4fd9-88c0-82a08f90fb5a 10 | 16-Nov-16,9,2017-04-02T16:23:36.000Z,2017-04-02T16:42:08.000Z,Manica,Manica,Bandula,Chirodzo,16,no,8,8,no,6,yes,no,yes,no,grass,burntbricks,NULL,earth,no,2,1,yes,3,3,yes,NULL,3,yes,['Oct' ; 'Nov'],6,yes,no,NULL,no,NULL,no,never,no,NULL,NULL,more_half,yes,yes,['oxen' ; 'cows' ; 'goats'],NULL,3,yes,no,['television' ; 'solar_panel' ; 'solar_torch'],NULL,3,['Jan' ; 'Dec'],['rely_less_food' ; 'limit_variety' ; 'limit_portion' ; 'restrict_adults' ; 'lab_ex_food'],-19.11221518,33.48343695,701,11,uuid:846103d2-b1db-4055-b502-9cd510bb7b37 11 | 16-Dec-16,10,2017-04-02T17:03:28.000Z,2017-04-02T17:25:11.000Z,Manica,Manica,Bandula,Chirodzo,22,no,12,12,no,23,no,no,no,no,mabatisloping,burntbricks,NULL,cement,yes,1,5,no,2,2,yes,NULL,2,yes,['Sept' ; 'Oct' ; 'Nov'],22,yes,no,NULL,no,NULL,no,never,no,NULL,NULL,more_half,yes,no,['oxen' ; 'cows'],NULL,2,yes,no,['cow_cart' ; 'motorcyle' ; 'bicycle' ; 'television' ; 'radio' ; 'cow_plough' ; 'solar_panel' ; 'solar_torch' ; 'table'],NULL,3,['Jan' ; 'Oct' ; 'Nov' ; 'Dec'],['rely_less_food' ; 'limit_portion' ; 'restrict_adults' ; 'lab_ex_food'],-19.1122147,33.48339436,710,14,uuid:8f4e49bc-da81-4356-ae34-e0d794a23721 12 | 21-Nov-16,11,2017-04-03T03:16:15.000Z,2017-04-03T03:31:10.000Z,Manica,Manica,Bandula,God,6,no,6,6,no,20,yes,yes,no,yes,grass,sunbricks,NULL,earth,no,2,1,no,2,2,no,2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,no,yes,['oxen' ; 'cows'],NULL,2,no,no,['radio' ; 'cow_plough'],NULL,2,['Oct' ; 'Nov'],['rely_less_food' ; 'lab_ex_food'],-19.11219126,33.48345933,707,10,uuid:d29b44e3-3348-4afc-aa4d-9eb34c89d483 13 | 21-Nov-16,12,2017-04-03T03:31:13.000Z,2017-04-03T03:58:34.000Z,Manica,Manica,Bandula,God,20,no,7,7,yes,20,no,no,no,no,mabatisloping,burntbricks,NULL,cement,no,2,3,no,2,2,yes,NULL,2,yes,['Aug' ; 'Sept' ; 'Oct' ; 'Nov'],20,yes,no,NULL,yes,no,no,never,no,NULL,NULL,more_half,no,no,['oxen' ; 'cows'],NULL,2,yes,no,['cow_cart' ; 'bicycle' ; 'radio' ; 'cow_plough' ; 'table'],NULL,3,['Sept' ; 'Oct'],['rely_less_food' ; 'limit_variety' ; 'reduce_meals' ; 'lab_ex_food'],-19.11229465,33.48341504,696,13,uuid:e6ee6269-b467-4e37-91fc-5e9eaf934557 14 | 21-Nov-16,13,2017-04-03T03:58:43.000Z,2017-04-03T04:19:36.000Z,Manica,Manica,Bandula,God,7,yes,6,6,no,8,yes,no,yes,no,grass,burntbricks,NULL,earth,no,1,1,no,4,4,yes,NULL,4,yes,['Oct'],7,yes,no,NULL,no,NULL,no,never,no,NULL,NULL,more_half,yes,no,['cows' ; 'goats' ; 'poultry'],NULL,3,yes,no,['bicycle' ; 'radio' ; 'cow_plough' ; 'mobile_phone'],NULL,2,['Sept' ; 'Oct' ; 'Nov'],['lab_ex_food'],-19.11236935,33.48355635,706,15,uuid:6c00c145-ee3b-409c-8c02-2c8d743b6918 15 | 21-Nov-16,14,2017-04-03T04:19:57.000Z,2017-04-03T04:50:05.000Z,Manica,Manica,Bandula,God,20,yes,10,10,no,20,yes,yes,no,yes,grass,burntbricks,NULL,earth,no,3,3,no,3,3,no,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,yes,yes,['oxen' ; 'cows' ; 'goats'],NULL,3,yes,no,['bicycle' ; 'radio' ; 'cow_plough' ; 'solar_panel' ; 'table' ; 'mobile_phone'],NULL,3,['June' ; 'July' ; 'Aug' ; 'Sept' ; 'Oct' ; 'Nov'],['reduce_meals' ; 'lab_ex_food'],-19.11222089,33.4834388,698,11,uuid:9b21467f-1116-4340-a3b1-1ab64f13c87d 16 | 21-Nov-16,15,2017-04-03T05:12:17.000Z,2017-04-03T05:28:44.000Z,Manica,Manica,Bandula,God,30,yes,5,5,no,30,yes,yes,yes,yes,grass,sunbricks,NULL,earth,no,1,2,yes,3,3,yes,NULL,3,yes,['Sept' ; 'Oct' ; 'Nov'],30,yes,no,NULL,yes,no,no,once,no,NULL,NULL,abt_half,no,no,['oxen' ; 'cows' ; 'goats'],NULL,3,yes,no,['bicycle' ; 'radio' ; 'cow_plough' ; 'solar_panel' ; 'table'],NULL,2,['Jan' ; 'Feb' ; 'Mar' ; 'Apr' ; 'May' ; 'June' ; 'July' ; 'Aug' ; 'Sept' ; 'Oct' ; 'Nov'],['na' ; 'rely_less_food' ; 'limit_portion' ; 'reduce_meals' ; 'lab_ex_food'],-19.1120793,33.48339657,715,9,uuid:a837e545-ff86-4a1c-a1a5-6186804b985f 17 | 24-Nov-16,16,2017-04-03T05:29:24.000Z,2017-04-03T05:40:53.000Z,Manica,Manica,Bandula,God,24,yes,6,6,no,47,yes,yes,yes,yes,grass,muddaub,NULL,earth,yes,2,1,yes,1,1,no,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,yes,yes,['oxen' ; 'cows' ; 'goats' ; 'poultry'],NULL,4,no,no,['radio' ; 'cow_plough' ; 'solar_panel' ; 'solar_torch'],NULL,3,['Jan' ; 'Feb'],['lab_ex_food'],-19.11210678,33.48344397,709,9,uuid:d17db52f-4b87-4768-b534-ea8f9704c565 18 | 21-Nov-16,17,2017-04-03T05:41:42.000Z,2017-04-03T05:57:57.000Z,Manica,Manica,Bandula,God,10,yes,8,8,no,20,no,no,no,no,grass,sunbricks,NULL,earth,no,2,1,no,3,3,no,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,no,yes,['goats'],NULL,1,no,yes,['mobile_phone'],NULL,2,['Nov' ; 'Dec'],['lab_ex_food'],-19.11218314,33.48346325,710,10,uuid:4707f3dc-df18-4348-9c2c-eec651e89b6b 19 | 21-Nov-16,18,2017-04-03T12:27:04.000Z,2017-04-03T12:39:48.000Z,Manica,Manica,Bandula,God,6,no,4,4,no,20,yes,yes,no,yes,grass,muddaub,NULL,earth,no,1,1,no,2,2,no,2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,no,yes,['goats' ; 'pigs' ; 'poultry'],NULL,3,yes,no,['bicycle' ; 'mobile_phone'],NULL,2,['Oct' ; 'Nov'],['reduce_meals' ; 'lab_ex_food'],-19.11133515,33.47630848,685,17,uuid:7ffe7bd1-a15c-420c-a137-e1f006c317a3 20 | 21-Nov-16,19,2017-04-03T12:40:14.000Z,2017-04-03T12:53:29.000Z,Manica,Manica,Bandula,God,20,yes,9,9,no,23,yes,yes,yes,yes,mabatisloping,burntbricks,NULL,earth,no,1,2,yes,2,2,no,2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,yes,yes,['oxen' ; 'goats'],NULL,2,yes,no,['bicycle' ; 'radio' ; 'cow_plough' ; 'solar_panel' ; 'solar_torch' ; 'mobile_phone'],NULL,3,['Oct' ; 'Nov' ; 'Dec'],['rely_less_food' ; 'limit_portion' ; 'lab_ex_food' ; 'seek_government'],-19.11142642,33.47640837,716,30,uuid:e32f2dc0-0d05-42fb-8e21-605757ddf07d 21 | 21-Nov-16,20,2017-04-03T14:04:50.000Z,2017-04-03T14:20:04.000Z,Manica,Manica,Bandula,God,24,yes,6,6,no,1,yes,yes,yes,yes,grass,burntbricks,NULL,earth,yes,1,1,no,2,2,no,2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,no,yes,['cows'],NULL,1,yes,yes,['bicycle' ; 'cow_plough' ; 'solar_torch'],NULL,2,['Oct' ; 'Nov'],['rely_less_food' ; 'lab_ex_food'],-19.11147317,33.47619213,700,27,uuid:d1005274-bf52-4e79-8380-3350dd7c2bac 22 | 21-Nov-16,21,2017-04-03T14:24:58.000Z,2017-04-03T14:44:39.000Z,Manica,Manica,Bandula,God,20,yes,8,8,no,20,no,yes,no,yes,mabatisloping,burntbricks,NULL,cement,no,1,1,no,4,4,yes,NULL,4,yes,['Oct'],20,yes,no,NULL,no,NULL,no,never,no,NULL,NULL,less_half,no,yes,['oxen' ; 'cows' ; 'goats'],NULL,3,yes,no,NULL,NULL,2,['Jan' ; 'Feb' ; 'Mar' ; 'Oct' ; 'Nov' ; 'Dec'],['rely_less_food' ; 'restrict_adults' ; 'day_night_hungry' ; 'lab_ex_food'],-19.11155014,33.47623134,707,20,uuid:6570a7d0-6a0b-452c-aa2e-922500e35749 23 | 21-Nov-16,22,2017-04-03T16:28:52.000Z,2017-04-03T16:40:47.000Z,Manica,Manica,Bandula,God,14,no,4,4,no,20,yes,yes,yes,yes,grass,muddaub,NULL,earth,no,1,1,no,1,1,no,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,no,yes,['goats'],NULL,1,yes,no,['radio'],NULL,2,['Jan' ; 'Feb' ; 'Mar' ; 'Apr' ; 'Aug' ; 'Sept' ; 'Oct' ; 'Nov' ; 'Dec'],['rely_less_food' ; 'reduce_meals' ; 'go_forest' ; 'lab_ex_food'],-19.11212691,33.48350764,722,9,uuid:a51c3006-8847-46ff-9d4e-d29919b8ecf9 24 | 21-Nov-16,23,2017-04-03T16:41:04.000Z,2017-04-03T17:04:28.000Z,Manica,Manica,Bandula,Ruaca,12,yes,10,10,no,20,no,no,no,no,mabatisloping,burntbricks,NULL,cement,yes,1,4,yes,2,2,no,2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,yes,no,['oxen' ; 'cows' ; 'goats'],NULL,3,yes,no,['cow_cart' ; 'bicycle' ; 'television' ; 'radio' ; 'cow_plough' ; 'solar_panel' ; 'electricity' ; 'mobile_phone'],NULL,3,['none'],['na'],-19.11219352,33.4833833,699,10,uuid:58b37b6d-d6cd-4414-8790-b9c68bca98de 25 | 21-Nov-16,24,2017-04-03T17:19:49.000Z,2017-04-03T17:43:01.000Z,Manica,Manica,Bandula,Ruaca,8,no,6,6,no,4,no,no,no,no,mabatisloping,burntbricks,NULL,cement,yes,2,2,yes,3,3,yes,NULL,3,yes,['Sept' ; 'Oct'],8,yes,no,NULL,no,NULL,no,never,no,NULL,NULL,less_half,yes,no,['oxen' ; 'cows' ; 'goats'],NULL,3,no,no,['radio' ; 'table' ; 'sofa_set' ; 'mobile_phone'],NULL,2,['Nov' ; 'Dec'],['lab_ex_food'],-19.11218803,33.48343475,745,11,uuid:661457d3-7e61-45e8-a238-7415e7548f82 26 | 21-Nov-16,25,2017-04-04T04:01:58.000Z,2017-04-04T04:29:47.000Z,Manica,Manica,Bandula,Ruaca,10,yes,11,11,no,6,no,no,no,no,mabatisloping,burntbricks,NULL,cement,no,2,3,yes,3,3,yes,NULL,3,yes,['Aug' ; 'Sept'],10,yes,no,NULL,no,NULL,no,never,yes,['business' ; 'non_farm_prod'],NULL,more_half,yes,no,['oxen' ; 'cows'],NULL,2,yes,no,['cow_cart' ; 'motorcyle' ; 'television' ; 'radio' ; 'cow_plough' ; 'solar_panel' ; 'solar_torch' ; 'table' ; 'sofa_set' ; 'mobile_phone'],NULL,2,['Jan' ; 'Feb' ; 'Oct'],['na'],-19.11223416,33.4834841,698,11,uuid:45ed84c4-114e-4df0-9f5d-c800806c2bee 27 | 21-Nov-16,26,2017-04-04T04:30:19.000Z,2017-04-04T04:44:19.000Z,Manica,Manica,Bandula,Ruaca,2,yes,3,3,no,20,yes,yes,yes,yes,mabatisloping,burntbricks,NULL,earth,no,2,2,no,2,2,yes,NULL,2,yes,['Oct' ; 'Nov'],2,yes,no,NULL,no,NULL,no,never,no,NULL,NULL,abt_half,yes,yes,['oxen' ; 'cows'],NULL,2,yes,no,['radio' ; 'cow_plough' ; 'table' ; 'mobile_phone'],NULL,2,['none'],['na'],-19.11230411,33.48354341,706,12,uuid:1c54ee24-22c4-4ee9-b1ad-42d483c08e2e 28 | 21-Nov-16,27,2017-04-05T04:59:42.000Z,2017-04-05T05:14:45.000Z,Manica,Manica,Bandula,Ruaca,36,no,7,7,no,36,no,no,no,no,grass,burntbricks,NULL,earth,no,3,2,yes,2,2,no,2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,no,no,['oxen' ; 'cows' ; 'poultry'],NULL,3,yes,no,['bicycle' ; 'radio' ; 'cow_plough' ; 'solar_panel' ; 'solar_torch' ; 'mobile_phone'],NULL,3,['none'],['na'],-19.0430007,33.40508367,679,14,uuid:3197cded-1fdc-4c0c-9b10-cfcc0bf49c4d 29 | 21-Nov-16,28,2017-04-05T05:14:49.000Z,2017-04-05T05:36:18.000Z,Manica,Manica,Bandula,Ruaca,2,no,2,2,no,2,no,no,no,no,grass,muddaub,NULL,earth,no,1,1,yes,3,3,yes,NULL,3,yes,['Aug' ; 'Sept' ; 'Oct' ; 'Nov'],2,yes,no,NULL,no,NULL,no,more_once,no,NULL,NULL,more_half,no,yes,['none'],NULL,1,yes,no,NULL,NULL,3,['Aug' ; 'Sept' ; 'Oct'],['rely_less_food' ; 'reduce_meals' ; 'borrow_food' ; 'go_forest' ; 'lab_ex_food'],-19.04290893,33.40506932,721,7,uuid:1de53318-a8cf-4736-99b1-8239f8822473 30 | 21-Nov-16,29,2017-04-05T05:37:30.000Z,2017-04-05T06:05:44.000Z,Manica,Manica,Bandula,Ruaca,10,yes,7,7,no,10,yes,no,yes,no,mabatisloping,burntbricks,NULL,earth,no,1,2,yes,3,3,yes,NULL,3,yes,['Sept' ; 'Oct' ; 'Nov'],4,yes,yes,['less_work'],yes,yes,no,frequently,no,NULL,NULL,more_half,no,no,['goats'],NULL,1,yes,no,['motorcyle' ; 'bicycle' ; 'radio' ; 'table' ; 'mobile_phone'],NULL,3,['Jan' ; 'Feb'],['rely_less_food' ; 'limit_variety'],-19.04302413,33.40507276,657,6,uuid:adcd7463-8943-4c67-b25f-f72311409476 31 | 21-Nov-16,30,2017-04-05T06:05:58.000Z,2017-04-05T06:20:39.000Z,Manica,Manica,Bandula,Ruaca,22,yes,7,7,yes,22,no,no,no,no,grass,muddaub,NULL,earth,no,1,2,no,1,1,no,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,no,yes,['none'],NULL,1,no,no,['bicycle' ; 'radio' ; 'mobile_phone'],NULL,2,['Jan' ; 'Feb'],['rely_less_food' ; 'limit_variety' ; 'limit_portion' ; 'restrict_adults' ; 'lab_ex_food'],-19.04300478,33.40505449,669,5,uuid:59341ead-92be-45a9-8545-6edf9f94fdc6 32 | 21-Nov-16,31,2017-04-05T06:21:20.000Z,2017-04-05T06:38:26.000Z,Manica,Manica,Bandula,Ruaca,15,yes,3,3,no,2,yes,yes,yes,yes,grass,muddaub,NULL,earth,no,7,1,no,1,1,no,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,no,no,['none'],NULL,1,no,no,NULL,NULL,3,['none'],['na'],-19.04302176,33.40509382,704,4,uuid:cb06eb49-dd39-4150-8bbe-a599e074afe8 33 | 21-Nov-16,32,2017-04-05T06:38:55.000Z,2017-04-05T08:05:32.000Z,Manica,Manica,Bandula,Ruaca,53,yes,19,19,yes,69,yes,yes,yes,no,mabatipitched,muddaub,NULL,earth,no,8,2,yes,8,8,yes,NULL,8,yes,['Sept' ; 'Oct'],45,yes,no,NULL,yes,no,no,more_once,yes,['farming'],NULL,more_half,yes,yes,['oxen' ; 'cows' ; 'goats' ; 'pigs' ; 'poultry'],NULL,5,yes,no,['cow_cart' ; 'motorcyle' ; 'radio' ; 'cow_plough' ; 'solar_panel' ; 'mobile_phone'],NULL,2,['none'],['na'],-19.04411399,33.40390565,703,8,uuid:25597af3-cd79-449c-a48a-fb9aea6c48bf 34 | 21-Nov-16,33,2017-04-05T08:08:19.000Z,2017-04-05T08:25:48.000Z,Manica,Manica,Bandula,Ruaca,20,yes,8,8,no,34,yes,yes,yes,yes,grass,muddaub,NULL,cement,no,2,1,no,2,2,yes,NULL,2,yes,['Aug' ; 'Sept' ; 'Oct'],20,yes,no,NULL,no,NULL,no,more_once,no,NULL,NULL,more_half,no,no,['oxen' ; 'poultry'],NULL,2,yes,no,['cow_cart' ; 'lorry' ; 'motorcyle' ; 'sterio' ; 'cow_plough' ; 'solar_panel' ; 'mobile_phone'],NULL,2,['none'],['na'],-19.04414887,33.40383602,695,5,uuid:0fbd2df1-2640-4550-9fbd-7317feaa4758 35 | 17-Nov-16,34,2017-04-05T16:00:47.000Z,2017-04-05T16:21:59.000Z,Manica,Manica,Bandula,Chirodzo,18,yes,8,8,no,18,no,no,no,no,mabatisloping,burntbricks,NULL,cement,yes,2,3,yes,2,2,yes,NULL,2,yes,['Oct' ; 'Nov'],2,yes,no,NULL,yes,no,no,more_once,no,NULL,NULL,more_half,no,no,['oxen' ; 'cows' ; 'goats'],NULL,3,yes,no,['television' ; 'radio' ; 'cow_plough' ; 'solar_panel' ; 'solar_torch' ; 'table' ; 'mobile_phone'],NULL,2,['Jan' ; 'Dec'],['rely_less_food' ; 'limit_variety' ; 'limit_portion' ; 'restrict_adults' ; 'lab_ex_food'],-19.11219065,33.48341559,706,11,uuid:14c78c45-a7cc-4b2a-b765-17c82b43feb4 36 | 17-Nov-16,35,2017-04-05T16:22:13.000Z,2017-04-05T16:50:25.000Z,Manica,Manica,Bandula,Chirodzo,45,yes,5,5,no,45,no,no,no,no,grass,muddaub,NULL,earth,no,3,1,no,2,2,yes,NULL,2,yes,['Sept' ; 'Oct' ; 'Nov'],20,yes,no,NULL,yes,no,no,more_once,no,NULL,NULL,more_half,no,yes,['oxen' ; 'cows'],NULL,2,yes,no,['bicycle' ; 'cow_plough'],NULL,3,['Jan' ; 'Sept' ; 'Oct' ; 'Nov' ; 'Dec'],['rely_less_food' ; 'limit_variety' ; 'limit_portion' ; 'reduce_meals' ; 'restrict_adults' ; 'go_forest'],-19.11211362,33.48342515,733,11,uuid:ff7496e7-984a-47d3-a8a1-13618b5683ce 37 | 17-Nov-16,36,2017-04-05T16:50:48.000Z,2017-04-05T17:10:53.000Z,Manica,Manica,Bandula,Chirodzo,23,yes,6,6,no,23,no,no,no,no,mabatisloping,sunbricks,NULL,earth,no,1,1,no,3,3,yes,NULL,3,no,NULL,23,yes,no,NULL,yes,no,no,once,no,NULL,NULL,abt_half,yes,yes,['oxen' ; 'cows' ; 'pigs'],NULL,3,no,no,['cow_cart' ; 'bicycle' ; 'radio' ; 'cow_plough' ; 'solar_panel' ; 'mobile_phone'],NULL,3,['none'],['na'],-19.11218058,33.4833843,710,10,uuid:c90eade0-1148-4a12-8c0e-6387a36f45b1 38 | 17-Nov-16,37,2017-04-05T17:17:48.000Z,2017-04-05T17:26:51.000Z,Manica,Manica,Bandula,Chirodzo,8,no,3,3,no,8,yes,yes,no,no,mabatisloping,burntbricks,NULL,earth,no,3,1,no,1,1,no,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,no,no,['oxen' ; 'cows'],NULL,2,yes,no,['bicycle' ; 'television' ; 'radio' ; 'cow_plough' ; 'solar_panel' ; 'solar_torch' ; 'mobile_phone'],NULL,3,['Jan' ; 'Nov' ; 'Dec'],['rely_less_food' ; 'limit_variety' ; 'lab_ex_food'],-19.11217951,33.48339525,711,12,uuid:408c6c93-d723-45ef-8dee-1b1bd3fe20cd 39 | 17-Nov-16,38,2017-04-05T17:28:12.000Z,2017-04-05T17:50:57.000Z,Manica,Manica,Bandula,God,19,yes,10,10,yes,19,no,no,no,no,grass,muddaub,NULL,earth,no,3,1,no,2,2,yes,NULL,2,yes,['Sept' ; 'Oct'],9,yes,no,NULL,yes,no,no,never,no,NULL,NULL,more_half,no,yes,['oxen' ; 'cows' ; 'goats'],NULL,3,yes,yes,['bicycle' ; 'radio' ; 'cow_plough' ; 'solar_panel' ; 'table' ; 'mobile_phone'],NULL,3,['Nov'],['limit_variety' ; 'lab_ex_food'],-19.11222939,33.48337467,696,9,uuid:81309594-ff58-4dc1-83a7-72af5952ee08 40 | 17-Nov-16,39,2017-04-06T08:31:17.000Z,2017-04-06T08:44:47.000Z,Manica,Manica,Bandula,God,22,yes,6,6,no,22,yes,yes,yes,yes,mabatisloping,muddaub,NULL,earth,no,1,1,no,1,1,no,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,no,no,['oxen'],NULL,1,yes,no,NULL,NULL,3,['Nov'],['lab_ex_food'],-19.0433618,33.4046671,0,20,uuid:c0fb6310-55af-4831-ae3d-2729556c3285 41 | 17-Nov-16,40,2017-04-06T08:44:51.000Z,2017-04-06T09:03:47.000Z,Manica,Manica,Bandula,God,23,yes,9,9,yes,23,no,yes,yes,yes,grass,burntbricks,NULL,earth,no,1,1,no,2,2,yes,NULL,2,yes,['Sept' ; 'Oct'],23,yes,no,NULL,yes,no,no,never,no,NULL,NULL,more_half,no,no,['oxen'],NULL,1,yes,no,['bicycle' ; 'radio' ; 'cow_plough' ; 'solar_panel' ; 'table' ; 'mobile_phone'],NULL,3,['Sept' ; 'Oct' ; 'Nov'],['lab_ex_food'],-19.0433618,33.4046671,0,22.112,uuid:c0b34854-eede-4e81-b183-ef58a45bfc34 42 | 17-Nov-16,41,2017-04-06T09:03:50.000Z,2017-04-06T09:14:05.000Z,Manica,Manica,Bandula,God,22,yes,7,7,no,22,yes,yes,yes,yes,grass,muddaub,NULL,earth,no,1,1,no,1,1,no,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,no,no,['oxen' ; 'poultry'],NULL,2,no,no,['motorcyle' ; 'bicycle' ; 'radio' ; 'cow_plough' ; 'table'],NULL,3,['Oct' ; 'Nov'],['limit_portion' ; 'reduce_meals'],-19.04339398,33.40485363,679,13,uuid:b3ba34d8-eea1-453d-bc73-c141bcbbc5e5 43 | 17-Nov-16,42,2017-04-06T09:14:22.000Z,2017-04-06T09:30:54.000Z,Manica,Manica,Bandula,God,8,yes,8,8,no,8,no,no,no,no,grass,sunbricks,NULL,earth,yes,1,1,no,2,2,yes,NULL,2,yes,['Aug' ; 'Sept'],5,yes,no,NULL,no,NULL,no,never,no,NULL,NULL,less_half,no,no,['cows' ; 'goats' ; 'poultry'],NULL,3,yes,no,['mobile_phone'],NULL,3,['Jan' ; 'Nov' ; 'Dec'],['rely_less_food' ; 'limit_variety' ; 'reduce_meals'],-19.04346041,33.40484617,699,10,uuid:e3a1dd8a-1bda-428c-a014-2b527f11ae64 44 | 17-Nov-16,43,2017-04-06T09:31:56.000Z,2017-04-06T09:53:53.000Z,Manica,Manica,Bandula,Chirodzo,3,no,7,7,no,29,no,no,no,no,grass,muddaub,NULL,earth,no,2,1,no,4,4,yes,NULL,4,no,NULL,3,yes,no,NULL,no,NULL,no,never,no,NULL,NULL,abt_half,yes,no,['oxen' ; 'cows'],NULL,2,no,no,['cow_plough' ; 'mobile_phone'],NULL,2,['Jan' ; 'Feb' ; 'Oct' ; 'Nov' ; 'Dec'],['lab_ex_food'],-19.04303063,33.40472726,605,30,uuid:b4dff49f-ef27-40e5-a9d1-acf287b47358 45 | 17-Nov-16,44,2017-04-06T14:44:32.000Z,2017-04-06T14:53:01.000Z,Manica,Manica,Bandula,Chirodzo,3,no,2,2,no,6,no,no,no,no,grass,muddaub,NULL,earth,no,2,1,no,1,1,no,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,yes,no,['oxen' ; 'cows' ; 'poultry'],NULL,3,yes,no,['radio' ; 'solar_torch'],NULL,2,['Jan' ; 'Dec'],['borrow_food'],-19.04315107,33.40458039,716,11,uuid:f9fadf44-d040-4fca-86c1-2835f79c4952 46 | 17-Nov-16,45,2017-04-06T14:53:04.000Z,2017-04-06T15:11:57.000Z,Manica,Manica,Bandula,Chirodzo,25,yes,9,9,no,7,no,no,no,no,grass,muddaub,NULL,earth,no,2,1,no,3,3,yes,NULL,3,yes,['Sept' ; 'Oct'],20,yes,no,NULL,no,NULL,no,never,yes,['farming' ; 'non_farm_prod'],NULL,more_half,yes,no,['oxen' ; 'cows' ; 'goats' ; 'poultry'],NULL,4,no,no,['motorcyle' ; 'bicycle' ; 'television' ; 'radio' ; 'cow_plough' ; 'solar_panel' ; 'solar_torch' ; 'table' ; 'mobile_phone'],NULL,3,['none'],['na'],-19.04312371,33.40466493,703,28,uuid:e3554d22-35b1-4fb9-b386-dd5866ad5792 47 | 17-Nov-16,46,2017-04-06T15:19:41.000Z,2017-04-06T15:45:32.000Z,Manica,Manica,Bandula,Chirodzo,21,yes,10,10,no,42,yes,yes,yes,yes,mabatisloping,burntbricks,NULL,cement,no,3,2,no,5,5,yes,NULL,5,yes,['Aug' ; 'Sept' ; 'Oct'],21,yes,no,NULL,no,NULL,no,once,no,NULL,NULL,more_half,yes,no,['oxen' ; 'poultry'],NULL,2,no,no,['motorcyle' ; 'computer' ; 'television' ; 'sterio' ; 'solar_panel' ; 'solar_torch' ; 'table' ; 'mobile_phone'],NULL,2,['Sept' ; 'Oct' ; 'Nov'],['lab_ex_food'],-19.04307032,33.40458421,703,5,uuid:35f297e0-aa5d-4149-9b7b-4965004cfc37 48 | 17-Nov-16,47,2017-04-07T14:05:25.000Z,2017-04-07T14:19:45.000Z,Manica,Manica,Bandula,Chirodzo,2,yes,2,2,no,2,yes,yes,yes,yes,grass,muddaub,NULL,earth,no,1,1,yes,2,2,yes,NULL,2,yes,['Sept' ; 'Oct' ; 'Nov'],2,yes,no,NULL,yes,no,no,once,no,NULL,NULL,more_half,no,no,['none'],NULL,1,no,no,['solar_torch' ; 'mobile_phone'],NULL,3,['none'],['na'],-19.11226093,33.48339791,689,5,uuid:2d0b1936-4f82-4ec3-a3b5-7c3c8cd6cc2b 49 | 16-Nov-16,48,2017-04-07T14:19:49.000Z,2017-04-07T14:40:23.000Z,Manica,Manica,Bandula,Chirodzo,48,yes,7,7,no,58,yes,no,yes,no,grass,muddaub,NULL,earth,no,1,1,no,1,1,no,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,no,no,['oxen' ; 'cows' ; 'poultry'],NULL,3,yes,no,['radio'],NULL,3,['June' ; 'July' ; 'Aug' ; 'Sept' ; 'Oct' ; 'Nov'],['limit_variety'],-19.11222978,33.48353345,689,12,uuid:e180899c-7614-49eb-a97c-40ed013a38a2 50 | 16-Nov-16,49,2017-04-07T14:43:09.000Z,2017-04-07T14:55:51.000Z,Manica,Manica,Bandula,49,12,no,6,6,no,26,yes,yes,yes,yes,mabatisloping,burntbricks,NULL,earth,yes,2,2,no,1,1,no,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,no,yes,['goats' ; 'poultry'],NULL,2,yes,no,['bicycle' ; 'radio' ; 'cow_plough' ; 'solar_panel' ; 'solar_torch' ; 'table' ; 'mobile_phone'],NULL,3,['Jan' ; 'Nov' ; 'Dec'],['reduce_meals' ; 'go_forest' ; 'lab_ex_food'],-19.11228265,33.48334844,694,12,uuid:2303ebc1-2b3c-475a-8916-b322ebf18440 51 | 16-Nov-16,50,2017-04-07T14:56:01.000Z,2017-04-07T15:26:23.000Z,Manica,Manica,Bandula,Chirodzo,6,yes,6,6,no,7,no,no,no,no,grass,muddaub,NULL,earth,no,1,1,no,1,1,yes,NULL,1,yes,['Sept' ; 'Oct'],1,no,no,NULL,yes,no,no,never,no,NULL,NULL,abt_half,yes,no,['poultry'],NULL,1,yes,no,['solar_torch'],NULL,2,['June' ; 'July' ; 'Aug' ; 'Sept' ; 'Oct' ; 'Nov' ; 'Dec'],['borrow_food' ; 'go_forest' ; 'lab_ex_food'],-19.11220496,33.48344521,718,12,uuid:4267c33c-53a7-46d9-8bd6-b96f58a4f92c 52 | 16-Nov-16,51,2017-04-07T15:27:45.000Z,2017-04-07T15:39:10.000Z,Manica,Manica,Bandula,Chirodzo,11,yes,5,5,no,30,yes,no,yes,no,grass,muddaub,NULL,cement,no,1,1,no,1,1,no,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,no,yes,['poultry'],NULL,1,no,no,['radio'],NULL,3,['Oct' ; 'Nov'],['go_forest' ; 'lab_ex_food'],-19.11221446,33.48338443,709,12,uuid:18ac8e77-bdaf-47ab-85a2-e4c947c9d3ce 53 | 16-Nov-16,52,2017-04-08T04:44:09.000Z,2017-04-08T05:02:58.000Z,Manica,Manica,Bandula,Chirodzo,15,yes,11,11,no,15,no,no,no,no,mabatisloping,burntbricks,NULL,cement,yes,1,3,yes,1,1,yes,NULL,1,yes,['Sept' ; 'Oct' ; 'Nov'],15,no,no,NULL,no,NULL,no,never,no,NULL,NULL,less_half,no,no,['oxen' ; 'cows' ; 'poultry'],NULL,3,yes,no,['motorcyle' ; 'television' ; 'radio' ; 'cow_plough' ; 'solar_panel' ; 'mobile_phone'],NULL,3,['Aug' ; 'Sept' ; 'Oct' ; 'Nov'],['limit_variety' ; 'reduce_meals'],-19.11223637,33.48335287,694,10,uuid:6db55cb4-a853-4000-9555-757b7fae2bcf 54 | 16-Nov-16,21,2017-04-08T05:03:08.000Z,2017-04-08T05:33:51.000Z,Manica,Manica,Bandula,Chirodzo,16,yes,8,8,yes,16,yes,yes,yes,yes,mabatisloping,burntbricks,NULL,cement,no,2,3,no,3,3,yes,NULL,3,yes,['Aug' ; 'Sept' ; 'Oct'],16,yes,no,NULL,yes,no,no,frequently,no,NULL,NULL,more_half,no,no,['oxen' ; 'goats'],NULL,2,yes,no,['bicycle' ; 'radio' ; 'mobile_phone'],NULL,2,['Nov'],['rely_less_food' ; 'limit_portion'],-19.11216571,33.48343865,687,10,uuid:cc7f75c5-d13e-43f3-97e5-4f4c03cb4b12 55 | 16-Nov-16,54,2017-04-08T05:36:55.000Z,2017-04-08T05:52:15.000Z,Manica,Manica,Bandula,Chirodzo,10,no,7,7,yes,15,yes,no,yes,no,grass,muddaub,NULL,earth,no,3,1,no,1,1,yes,NULL,1,yes,['Aug' ; 'Sept' ; 'Oct' ; 'Nov' ; 'Dec'],10,yes,no,NULL,no,NULL,no,never,no,NULL,NULL,more_half,no,no,['none'],NULL,1,yes,no,NULL,NULL,2,['Sept' ; 'Oct' ; 'Nov'],['rely_less_food' ; 'lab_ex_food'],-19.11220247,33.48335527,681,9,uuid:273ab27f-9be3-4f3b-83c9-d3e1592de919 56 | 16-Nov-16,55,2017-04-08T05:52:32.000Z,2017-04-08T06:05:41.000Z,Manica,Manica,Bandula,Chirodzo,23,yes,9,9,no,23,yes,no,yes,no,grass,muddaub,NULL,earth,no,2,2,no,1,1,no,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,no,no,['goats'],NULL,1,yes,no,['television' ; 'cow_plough' ; 'mobile_phone'],NULL,2,['Oct' ; 'Nov'],['lab_ex_food'],-19.11228974,33.48333393,702,11,uuid:883c0433-9891-4121-bc63-744f082c1fa0 57 | 16-Nov-16,56,2017-04-08T06:05:59.000Z,2017-04-08T06:26:12.000Z,Manica,Manica,Bandula,Chirodzo,23,yes,12,12,no,23,yes,yes,yes,yes,mabatisloping,burntbricks,NULL,cement,no,4,2,no,2,2,yes,NULL,2,yes,['Sept' ; 'Oct'],23,yes,no,NULL,yes,no,no,never,no,NULL,NULL,more_half,no,no,['oxen' ; 'goats'],NULL,2,yes,no,['motorcyle' ; 'bicycle' ; 'mobile_phone'],NULL,3,['none'],['na'],-19.11217264,33.48341837,689,10,uuid:973c4ac6-f887-48e7-aeaf-4476f2cfab76 58 | 16-Nov-16,57,2017-04-08T06:26:22.000Z,2017-04-08T06:39:40.000Z,Manica,Manica,Bandula,Chirodzo,20,yes,4,4,no,27,yes,yes,yes,yes,grass,burntbricks,NULL,earth,no,4,1,no,2,2,yes,NULL,2,no,NULL,20,yes,no,NULL,no,NULL,no,never,no,NULL,NULL,less_half,no,no,['none'],NULL,1,no,no,['radio'],NULL,2,['none'],['na'],-19.11227947,33.48338576,695,10,uuid:a7184e55-0615-492d-9835-8f44f3b03a71 59 | 16-Nov-16,58,2017-04-08T08:25:49.000Z,2017-04-08T08:48:51.000Z,Manica,Manica,Bandula,Chirodzo,35,yes,11,11,no,45,yes,yes,yes,yes,mabatisloping,burntbricks,NULL,earth,no,5,3,no,3,3,yes,NULL,3,no,NULL,35,yes,no,NULL,no,NULL,no,never,no,NULL,NULL,more_half,no,no,['oxen' ; 'cows' ; 'goats'],NULL,3,no,no,['motorcyle' ; 'bicycle' ; 'television' ; 'radio' ; 'cow_plough' ; 'solar_panel' ; 'mobile_phone'],NULL,2,['none'],['na'],-19.1121758,33.48332076,723,11,uuid:a7a3451f-cd0d-4027-82d9-8dcd1234fcca 60 | 16-Nov-16,59,2017-04-08T08:52:05.000Z,2017-04-08T09:02:34.000Z,Manica,Manica,Bandula,Chirodzo,60,no,2,2,no,60,yes,yes,yes,yes,grass,muddaub,NULL,earth,no,1,3,yes,2,2,no,2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,no,no,['oxen' ; 'cows' ; 'poultry'],NULL,3,no,no,NULL,NULL,2,['none'],['na'],-19.1123395,33.48333251,683,13,uuid:1936db62-5732-45dc-98ff-9b3ac7a22518 61 | 16-Nov-16,60,2017-04-08T09:03:01.000Z,2017-04-08T09:20:18.000Z,Manica,Bandula,Bandula,Chirodzo,12,yes,8,8,no,15,yes,yes,yes,yes,grass,burntbricks,NULL,earth,no,3,2,no,3,3,yes,NULL,3,yes,['Aug' ; 'Sept' ; 'Oct'],12,yes,no,NULL,no,NULL,no,never,no,NULL,NULL,more_half,yes,yes,['oxen' ; 'cows' ; 'goats' ; 'poultry'],NULL,4,yes,no,['cow_plough'],NULL,2,['none'],['na'],-19.11225763,33.48341208,694,11,uuid:85465caf-23e4-4283-bb72-a0ef30e30176 62 | 16-Nov-16,61,2017-04-08T10:47:11.000Z,2017-04-08T11:14:09.000Z,Manica,Manica,Bandula,Chirodzo,14,yes,10,10,no,14,no,yes,yes,yes,grass,muddaub,NULL,earth,no,4,1,no,2,2,yes,NULL,2,yes,['Aug' ; 'Sept' ; 'Oct'],13,yes,no,NULL,yes,yes,no,more_once,no,NULL,NULL,more_half,yes,no,['oxen' ; 'cows' ; 'goats'],NULL,3,yes,no,['cow_cart' ; 'motorcyle' ; 'bicycle' ; 'television' ; 'radio' ; 'cow_plough' ; 'solar_panel' ; 'table' ; 'mobile_phone'],NULL,3,['Jan' ; 'Feb' ; 'Dec'],['rely_less_food' ; 'limit_variety' ; 'reduce_meals' ; 'restrict_adults'],-19.11218035,33.48341635,712,13,uuid:2401cf50-8859-44d9-bd14-1bf9128766f2 63 | 16-Nov-16,62,2017-04-08T13:27:58.000Z,2017-04-08T13:41:21.000Z,Manica,Manica,Bandula,Chirodzo,5,no,5,5,no,5,yes,no,no,no,grass,muddaub,NULL,earth,no,3,1,no,2,2,no,2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,no,yes,['none'],NULL,1,no,no,['bicycle' ; 'radio' ; 'mobile_phone'],NULL,3,['Aug' ; 'Sept' ; 'Oct' ; 'Nov'],['rely_less_food' ; 'limit_variety' ; 'limit_portion' ; 'reduce_meals' ; 'restrict_adults' ; 'borrow_food' ; 'go_forest' ; 'lab_ex_food'],-19.11216869,33.48339699,719,18,uuid:c6597ecc-cc2a-4c35-a6dc-e62c71b345d6 64 | 16-Nov-16,63,2017-04-08T13:41:39.000Z,2017-04-08T13:52:07.000Z,Manica,Manica,Bandula,Chirodzo,1,yes,4,4,no,10,yes,yes,no,yes,grass,muddaub,NULL,earth,no,1,1,yes,1,1,no,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,no,yes,['none'],NULL,1,no,no,NULL,NULL,3,['Jan' ; 'Oct' ; 'Nov' ; 'Dec'],['rely_less_food' ; 'limit_variety' ; 'reduce_meals' ; 'restrict_adults'],-19.11220024,33.4833903,702,25,uuid:86ed4328-7688-462f-aac7-d6518414526a 65 | 16-Nov-16,64,2017-04-08T13:52:30.000Z,2017-04-08T14:02:24.000Z,Manica,Manica,Bandula,Chirodzo,1,no,6,6,no,1,no,no,no,no,grass,muddaub,NULL,earth,no,2,1,no,2,2,no,2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,no,no,['goats'],NULL,1,yes,no,['bicycle' ; 'solar_torch' ; 'table' ; 'sofa_set' ; 'mobile_phone'],NULL,3,['Jan' ; 'Feb' ; 'Dec'],['rely_less_food' ; 'limit_variety' ; 'reduce_meals' ; 'restrict_adults' ; 'lab_ex_food'],-19.1121962,33.48339576,704,9,uuid:28cfd718-bf62-4d90-8100-55fafbe45d06 66 | 16-Nov-16,65,2017-04-08T14:02:49.000Z,2017-04-08T14:15:45.000Z,Manica,Manica,Bandula,Chirodzo,20,no,8,8,no,20,no,no,no,no,mabatisloping,burntbricks,NULL,earth,no,2,3,no,2,2,yes,NULL,2,yes,['Sept' ; 'Oct' ; 'Nov'],20,yes,no,NULL,no,NULL,no,once,no,NULL,NULL,abt_half,no,no,['oxen' ; 'cows' ; 'goats'],NULL,3,yes,no,['motorcyle' ; 'radio' ; 'cow_plough' ; 'table'],NULL,3,['Jan' ; 'Feb' ; 'Mar'],['rely_less_food' ; 'limit_variety' ; 'reduce_meals' ; 'lab_ex_food'],-19.11221474,33.48341209,706,39,uuid:143f7478-0126-4fbc-86e0-5d324339206b 67 | 16-Nov-16,66,2017-04-08T21:09:38.000Z,2017-04-08T21:33:45.000Z,Manica,Manica,Bandula,Chirodzo,16,yes,10,10,no,37,yes,no,no,no,mabatipitched,burntbricks,NULL,cement,yes,5,3,yes,1,1,yes,NULL,1,yes,['Aug' ; 'Sept' ; 'Oct'],10,no,no,NULL,yes,no,no,frequently,no,NULL,NULL,more_half,yes,no,['oxen' ; 'cows' ; 'goats' ; 'donkeys'],NULL,4,yes,no,['cow_cart' ; 'motorcyle' ; 'bicycle' ; 'television' ; 'radio' ; 'cow_plough' ; 'solar_panel' ; 'solar_torch' ; 'mobile_phone'],NULL,3,['none'],['na'],-19.1121722,33.48339142,702,8,uuid:a457eab8-971b-4417-a971-2e55b8702816 68 | 16-Nov-16,67,2017-04-08T21:34:23.000Z,2017-04-08T21:49:02.000Z,Manica,Manica,Bandula,Chirodzo,9,yes,5,5,no,31,yes,no,yes,no,mabatipitched,burntbricks,NULL,cement,yes,1,2,no,1,1,yes,NULL,1,yes,['Oct' ; 'Nov'],9,yes,no,NULL,no,NULL,no,more_once,no,NULL,NULL,more_half,yes,yes,['oxen' ; 'cows' ; 'goats' ; 'donkeys'],NULL,4,yes,no,['motorcyle' ; 'radio' ; 'cow_plough' ; 'solar_panel' ; 'mobile_phone'],NULL,3,['none'],['na'],-19.11209398,33.48338805,717,11,uuid:6c15d667-2860-47e3-a5e7-7f679271e419 69 | 16-Nov-16,68,2017-04-08T21:49:40.000Z,2017-04-09T22:06:57.000Z,Manica,Manica,Bandula,Chirodzo,21,yes,8,8,no,52,yes,yes,no,no,mabatipitched,burntbricks,NULL,earth,no,3,3,no,3,3,yes,NULL,3,yes,['Nov' ; 'Dec'],21,yes,no,NULL,no,NULL,no,more_once,no,NULL,NULL,more_half,no,no,['oxen' ; 'cows' ; 'goats'],NULL,3,yes,no,['motorcyle' ; 'television' ; 'sterio' ; 'solar_panel' ; 'mobile_phone'],NULL,3,['none'],['na'],-19.11214985,33.4834782,710,10,uuid:ef04b3eb-b47d-412e-9b09-4f5e08fc66f9 70 | 16-Nov-16,69,2017-04-09T22:08:07.000Z,2017-04-09T22:21:08.000Z,Manica,Manica,Bandula,Chirodzo,12,yes,4,4,no,12,no,no,no,no,grass,muddaub,NULL,earth,no,2,1,no,1,1,yes,NULL,1,yes,['Nov' ; 'Dec'],12,yes,no,NULL,no,NULL,no,more_once,no,NULL,NULL,more_half,no,no,['goats'],NULL,1,yes,no,['bicycle' ; 'radio' ; 'solar_torch' ; 'mobile_phone'],NULL,3,['none'],['na'],-19.11216693,33.48340465,708,8,uuid:f86933a5-12b8-4427-b821-43c5b039401d 71 | 16-Nov-16,70,2017-04-09T22:21:23.000Z,2017-04-09T22:40:57.000Z,Manica,Manica,Bandula,Chirodzo,20,yes,8,8,no,25,no,yes,no,no,mabatipitched,burntbricks,NULL,earth,no,2,2,yes,3,3,yes,NULL,3,yes,['Aug' ; 'Sept'],20,yes,no,NULL,no,NULL,no,more_once,no,NULL,NULL,more_half,no,yes,['oxen' ; 'cows' ; 'goats' ; 'poultry'],NULL,4,no,no,['cow_cart' ; 'bicycle' ; 'radio' ; 'cow_plough' ; 'solar_panel' ; 'mobile_phone'],NULL,2,['none'],['na'],-19.11217415,33.48341471,707,8,uuid:1feb0108-4599-4bf9-8a07-1f5e66a50a0a 72 | 18-Nov-16,71,2017-04-09T15:00:19.000Z,2017-04-09T15:19:22.000Z,Manica,Manica,Bandula,Ruaca,12,yes,6,6,no,14,yes,yes,yes,yes,grass,burntbricks,NULL,earth,no,1,1,no,2,2,yes,NULL,2,yes,['Sept' ; 'Oct' ; 'Nov'],1,yes,no,NULL,yes,no,no,more_once,no,NULL,NULL,more_half,no,yes,['oxen' ; 'goats' ; 'poultry'],NULL,3,no,no,['radio' ; 'cow_plough' ; 'mobile_phone'],NULL,2,['Aug' ; 'Sept' ; 'Oct' ; 'Nov'],['rely_less_food' ; 'limit_variety' ; 'limit_portion' ; 'reduce_meals' ; 'restrict_adults' ; 'borrow_food' ; 'lab_ex_food'],-19.11220603,33.48332601,696,4,uuid:761f9c49-ec93-4932-ba4c-cc7b78dfcef1 73 | 16-Nov-16,127,2017-04-09T05:16:06.000Z,2017-04-09T05:27:41.000Z,Manica,Manica,Bandula,Chirodzo,10,yes,4,4,no,18,no,no,no,no,grass,burntbricks,NULL,earth,no,3,8,no,1,1,no,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,no,no,['pigs'],NULL,1,no,no,['mobile_phone'],NULL,2,['Aug' ; 'Sept' ; 'Oct'],['borrow_food' ; 'lab_ex_food'],-19.11221396,33.48341359,676,8,uuid:f6d04b41-b539-4e00-868a-0f62b427587d 74 | 23-Nov-16,133,2017-04-09T05:27:46.000Z,2017-04-09T05:43:51.000Z,Manica,Manica,Bandula,Ruaca,2,no,5,5,yes,25,no,no,no,no,mabatisloping,burntbricks,NULL,earth,no,1,2,yes,1,1,yes,NULL,1,yes,['Nov'],2,yes,no,NULL,no,NULL,no,never,no,NULL,NULL,abt_half,no,yes,['oxen' ; 'cows' ; 'goats' ; 'sheep' ; 'poultry'],NULL,5,yes,no,['cow_cart' ; 'car' ; 'lorry' ; 'motorcyle' ; 'bicycle' ; 'television' ; 'sterio' ; 'cow_plough' ; 'solar_panel' ; 'solar_torch' ; 'electricity' ; 'table' ; 'sofa_set' ; 'mobile_phone' ; 'fridge'],NULL,3,['Jan' ; 'Oct' ; 'Nov'],['na'],-19.1041288,33.4777622,0,2099.999,uuid:429d279a-a519-4dcc-9f64-4673b0fd5d53 75 | 24-Nov-16,152,2017-04-09T05:47:31.000Z,2017-04-09T06:16:11.000Z,Manica,Manica,Bandula,Ruaca,15,yes,10,10,no,16,yes,no,yes,no,grass,burntbricks,NULL,cement,no,3,1,no,2,2,yes,NULL,2,yes,['Sept' ; 'Oct' ; 'Nov'],16,yes,no,NULL,yes,no,no,once,no,NULL,NULL,abt_half,no,no,['oxen' ; 'cows' ; 'goats'],NULL,3,yes,yes,['motorcyle' ; 'bicycle' ; 'radio' ; 'sterio' ; 'cow_plough' ; 'solar_panel' ; 'mobile_phone'],NULL,3,['none'],['na'],-19.1121034,33.48344669,702,11,uuid:59738c17-1cda-49ee-a563-acd76f6bc487 76 | 24-Nov-16,153,2017-04-09T06:16:49.000Z,2017-04-09T06:28:48.000Z,Manica,Manica,Bandula,Ruaca,41,no,5,5,no,41,yes,yes,yes,yes,grass,burntbricks,NULL,earth,no,1,1,no,1,1,no,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,no,yes,['goats'],NULL,1,yes,no,NULL,NULL,2,['Oct' ; 'Nov'],['rely_less_food' ; 'limit_variety' ; 'limit_portion' ; 'reduce_meals' ; 'no_food' ; 'day_night_hungry'],-19.11223572,33.48345393,691,12,uuid:7e7961ca-fa1c-4567-9bfa-a02f876e4e03 77 | 24-Nov-16,155,2017-04-09T06:35:16.000Z,2017-04-09T06:48:01.000Z,Manica,Manica,Bandula,God,5,no,4,4,no,4,no,no,no,no,grass,burntbricks,NULL,earth,no,2,1,no,2,2,no,2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,yes,no,['none'],NULL,1,yes,no,['electricity'],NULL,2,['Jan' ; 'Sept' ; 'Oct' ; 'Nov' ; 'Dec'],['limit_variety' ; 'reduce_meals' ; 'borrow_food' ; 'go_forest' ; 'lab_ex_food'],-19.11220708,33.48342364,713,13,uuid:77b3021b-a9d6-4276-aaeb-5bfcfd413852 78 | 25-Nov-16,178,2017-04-09T06:54:49.000Z,2017-04-09T07:14:16.000Z,Manica,Manica,Bandula,Ruaca,20,yes,5,5,no,79,yes,yes,yes,no,mabatisloping,burntbricks,NULL,earth,no,1,2,yes,3,3,yes,NULL,3,yes,['Oct' ; 'Nov'],20,yes,no,NULL,yes,yes,no,frequently,no,NULL,NULL,abt_half,yes,yes,['oxen' ; 'cows' ; 'goats'],NULL,3,no,no,['radio' ; 'cow_plough' ; 'solar_panel' ; 'mobile_phone'],NULL,3,['none'],['na'],-19.1123581,33.48355586,714,50,uuid:2186e2ec-f65a-47cc-9bc1-a0f36dd9591c 79 | 25-Nov-16,177,2017-04-09T07:59:49.000Z,2017-04-09T08:22:34.000Z,Manica,Manica,Bandula,God,11,yes,10,10,no,13,no,no,no,no,grass,sunbricks,NULL,earth,no,2,1,no,2,2,yes,NULL,2,yes,['Oct' ; 'Nov'],11,no,no,NULL,no,NULL,no,more_once,no,NULL,NULL,more_half,yes,no,['oxen' ; 'cows'],NULL,2,yes,no,['motorcyle' ; 'television' ; 'cow_plough' ; 'solar_panel' ; 'mobile_phone'],NULL,3,['Nov'],['na'],-19.1120537,33.48349493,713,9,uuid:87998c33-c8d2-49ec-9dae-c123735957ec 80 | 25-Nov-16,180,2017-04-09T08:23:05.000Z,2017-04-09T08:42:02.000Z,Manica,Manica,Bandula,Ruaca,4,no,7,7,no,50,yes,yes,yes,yes,grass,muddaub,NULL,earth,no,1,1,yes,2,2,yes,NULL,2,yes,['Aug' ; 'Sept' ; 'Oct' ; 'Nov'],4,yes,no,NULL,no,NULL,no,never,no,NULL,NULL,abt_half,no,yes,['oxen' ; 'cows' ; 'goats'],NULL,3,yes,no,['cow_plough' ; 'solar_panel'],NULL,3,['Oct' ; 'Nov'],['rely_less_food' ; 'reduce_meals' ; 'lab_ex_food'],-19.11204921,33.48346659,701,4,uuid:ece89122-ea99-4378-b67e-a170127ec4e6 81 | 25-Nov-16,181,2017-04-09T08:43:08.000Z,2017-04-09T09:07:48.000Z,Manica,Manica,Bandula,God,20,yes,11,11,no,25,yes,no,yes,no,mabatipitched,sunbricks,NULL,earth,yes,4,2,yes,1,1,yes,NULL,1,yes,['Sept' ; 'Oct'],23,yes,no,NULL,yes,no,no,more_once,no,NULL,NULL,more_half,no,no,['oxen' ; 'cows' ; 'goats'],NULL,3,yes,no,['cow_cart' ; 'motorcyle' ; 'bicycle' ; 'television' ; 'radio' ; 'cow_plough' ; 'solar_panel' ; 'mobile_phone'],NULL,3,['none'],['na'],-19.11207501,33.48351086,701,5,uuid:bf373763-dca5-4906-901b-d1bacb4f0286 82 | 25-Nov-16,182,2017-04-09T09:08:04.000Z,2017-04-09T09:34:12.000Z,Manica,Manica,Bandula,God,20,no,7,7,no,21,no,no,no,no,mabatipitched,muddaub,NULL,earth,no,2,3,yes,1,1,yes,NULL,1,yes,['Sept' ; 'Oct' ; 'Nov'],20,yes,no,NULL,no,NULL,no,more_once,no,NULL,NULL,more_half,no,no,['oxen' ; 'cows'],NULL,2,yes,no,['solar_panel'],NULL,3,['Jan' ; 'Feb' ; 'Nov' ; 'Dec'],['na'],-19.11204151,33.48345447,694,4,uuid:394033e8-a6e2-4e39-bfac-458753a1ed78 83 | 28-Nov-16,186,2017-04-09T15:20:26.000Z,2017-04-09T15:46:14.000Z,Manica,Manica,Manica,God,24,no,7,7,no,24,yes,no,yes,no,grass,muddaub,NULL,earth,no,1,1,no,1,1,yes,NULL,1,yes,['Sept' ; 'Oct'],21,yes,no,NULL,no,NULL,no,more_once,no,NULL,NULL,more_half,no,no,['oxen' ; 'cows'],NULL,2,no,no,['cow_plough' ; 'mobile_phone'],NULL,3,['none'],['na'],-19.11232028,33.48346266,690,10,uuid:268bfd97-991c-473f-bd51-bc80676c65c6 84 | 28-Nov-16,187,2017-04-09T15:48:14.000Z,2017-04-09T16:12:46.000Z,Manica,Manica,Bandula,God,1,yes,5,5,no,43,yes,no,no,yes,grass,muddaub,NULL,earth,no,3,2,yes,2,2,yes,NULL,2,yes,['Sept' ; 'Oct' ; 'Nov'],24,yes,no,NULL,yes,no,no,more_once,no,NULL,NULL,more_half,no,no,['oxen' ; 'cows' ; 'goats' ; 'poultry'],NULL,4,yes,no,['cow_cart' ; 'motorcyle' ; 'bicycle' ; 'television' ; 'radio' ; 'cow_plough' ; 'solar_panel' ; 'solar_torch' ; 'mobile_phone'],NULL,3,['none'],['na'],-19.1122345,33.48349248,691,13,uuid:0a42c9ee-a840-4dda-8123-15c1bede5dfc 85 | 28-Nov-16,195,2017-04-09T16:13:19.000Z,2017-04-09T16:35:24.000Z,Manica,Manica,Bandula,God,7,yes,5,5,no,48,yes,yes,no,no,grass,burntbricks,NULL,earth,no,3,1,no,3,3,yes,NULL,3,yes,['Sept' ; 'Oct' ; 'Nov'],5,yes,no,NULL,no,NULL,no,never,no,NULL,NULL,more_half,yes,no,['oxen' ; 'cows' ; 'poultry'],NULL,3,no,no,['cow_cart' ; 'bicycle' ; 'radio' ; 'cow_plough' ; 'solar_torch'],NULL,2,['Sept' ; 'Oct' ; 'Nov'],['lab_ex_food'],-19.11220559,33.48342104,706,9,uuid:2c132929-9c8f-450a-81ff-367360ce2c19 86 | 28-Nov-16,196,2017-04-09T18:00:41.000Z,2017-04-09T18:31:40.000Z,Manica,Manica,Bandula,God,21,yes,7,7,no,49,yes,yes,yes,yes,mabatisloping,burntbricks,NULL,earth,no,2,2,no,2,2,yes,NULL,2,yes,['Oct' ; 'Nov'],21,yes,no,NULL,yes,no,no,more_once,no,NULL,NULL,more_half,no,no,['oxen' ; 'cows' ; 'goats'],NULL,3,yes,no,['radio' ; 'cow_plough' ; 'mobile_phone'],NULL,3,['none'],['na'],-19.11220357,33.48340018,694,10,uuid:44e427d1-a448-4bf2-b529-7d67b2266c06 87 | 28-Nov-16,197,2017-04-09T18:32:09.000Z,2017-04-09T19:14:52.000Z,Manica,Manica,Bandula,God,11,no,5,5,yes,19,yes,yes,no,no,mabatisloping,burntbricks,NULL,cement,yes,1,2,no,2,2,yes,NULL,2,yes,['Aug' ; 'Sept' ; 'Oct' ; 'Nov'],11,yes,no,NULL,no,NULL,no,more_once,no,NULL,NULL,more_half,yes,no,['oxen' ; 'cows' ; 'goats'],NULL,3,yes,yes,['bicycle' ; 'television' ; 'radio' ; 'cow_plough' ; 'solar_torch' ; 'table' ; 'mobile_phone'],NULL,2,['Nov'],['rely_less_food' ; 'limit_variety' ; 'reduce_meals'],-19.11218716,33.4833828,714,11,uuid:85c99fd2-775f-40c9-8654-68223f59d091 88 | 28-Nov-16,198,2017-04-09T19:15:21.000Z,2017-04-09T19:27:56.000Z,Manica,Manica,Bandula,God,11,no,3,3,no,49,no,no,no,no,grass,burntbricks,NULL,earth,no,1,1,no,2,2,yes,NULL,2,yes,['Jan' ; 'Dec'],11,yes,no,NULL,no,NULL,no,never,no,NULL,NULL,less_half,yes,no,['none'],NULL,1,yes,no,NULL,NULL,3,['Nov'],['reduce_meals' ; 'lab_ex_food'],-19.11212338,33.48338774,716,7,uuid:28c64954-739c-444c-a6e0-355878e471c8 89 | 21-Nov-16,201,2017-04-09T19:31:47.000Z,2017-04-09T19:45:38.000Z,Manica,Manica,Bandula,God,6,yes,4,4,no,6,yes,yes,yes,yes,grass,muddaub,NULL,earth,no,1,2,no,2,2,no,2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,no,yes,['oxen' ; 'cows'],NULL,2,yes,no,['bicycle' ; 'radio' ; 'solar_torch' ; 'mobile_phone'],NULL,2,['Oct' ; 'Nov' ; 'Dec'],['borrow_food' ; 'lab_ex_food'],-19.11217226,33.48338504,685,10,uuid:9e79a31c-3ea5-44f0-80f9-a32db49422e3 90 | 17-Nov-16,202,2017-04-09T19:48:09.000Z,2017-04-09T20:08:15.000Z,Manica,Manica,Bandula,God,12,yes,12,12,no,12,no,no,no,no,mabatisloping,burntbricks,NULL,cement,no,2,4,yes,2,2,yes,NULL,2,yes,['Aug' ; 'Sept' ; 'Oct' ; 'Nov' ; 'Dec'],9,yes,no,NULL,yes,no,no,more_once,no,NULL,NULL,more_half,no,yes,['oxen' ; 'cows' ; 'goats'],NULL,3,yes,no,['cow_cart' ; 'radio' ; 'cow_plough' ; 'solar_panel' ; 'solar_torch' ; 'table' ; 'mobile_phone'],NULL,3,['Jan' ; 'Feb' ; 'Mar' ; 'Oct' ; 'Nov' ; 'Dec'],['rely_less_food' ; 'limit_variety' ; 'reduce_meals' ; 'restrict_adults' ; 'lab_ex_food'],-19.11218863,33.48340466,705,5,uuid:06d39051-38ef-4757-b68b-3327b1f16b9d 91 | 26-Apr-17,72,2017-04-26T15:46:24.000Z,2017-04-26T16:13:33.000Z,Manica,Manica,Bandula,Ruaca,24,yes,6,6,no,24,yes,yes,yes,yes,grass,muddaub,NULL,earth,no,2,1,no,3,3,yes,NULL,3,yes,['Aug' ; 'Sept' ; 'Oct' ; 'Nov'],4,yes,no,NULL,yes,yes,no,more_once,no,NULL,NULL,more_half,no,yes,['oxen' ; 'cows' ; 'goats'],NULL,3,yes,no,['bicycle' ; 'radio' ; 'cow_plough'],NULL,2,['Jan' ; 'Aug' ; 'Sept' ; 'Oct' ; 'Nov' ; 'Dec'],['rely_less_food' ; 'limit_variety' ; 'limit_portion' ; 'reduce_meals' ; 'lab_ex_food'],-19.11221489,33.48347358,716,5,uuid:c4a2c982-244e-45a5-aa4b-71fa53f99e18 92 | 26-Apr-17,73,2017-04-26T16:13:50.000Z,2017-04-26T16:45:01.000Z,Manica,Manica,Bandula,Ruaca,6,yes,7,7,no,9,yes,no,no,no,mabatisloping,burntbricks,NULL,cement,no,2,2,no,3,3,yes,NULL,3,yes,['Sept' ; 'Oct' ; 'Nov'],4,yes,yes,['cheaper' ; 'less_work' ; 'train_outside_org'],yes,no,no,more_once,no,NULL,NULL,more_half,yes,no,['oxen' ; 'cows' ; 'goats'],NULL,3,yes,no,['cow_cart' ; 'motorcyle' ; 'bicycle' ; 'television' ; 'radio' ; 'cow_plough' ; 'solar_panel' ; 'table' ; 'mobile_phone'],NULL,3,['Jan' ; 'Sept' ; 'Oct'],['rely_less_food' ; 'limit_variety'],-19.11219747,33.48341488,714,4,uuid:ac3da862-9e6c-4962-94b6-f4c31624f207 93 | 26-Apr-17,76,2017-04-26T16:45:28.000Z,2017-04-26T17:26:21.000Z,Manica,Manica,Bandula,Ruaca,22,yes,17,17,no,48,yes,yes,yes,yes,mabatipitched,burntbricks,NULL,cement,no,5,2,no,6,6,yes,NULL,6,yes,['Sept' ; 'Oct'],22,yes,no,NULL,yes,yes,no,more_once,no,NULL,NULL,more_half,no,no,['oxen' ; 'cows' ; 'goats' ; 'poultry'],NULL,4,yes,no,['bicycle' ; 'radio' ; 'cow_plough' ; 'solar_panel' ; 'mobile_phone'],NULL,3,['none'],['na'],-19.11220193,33.48341762,702,9,uuid:4178a296-903a-4a8e-9cfa-0cd6143476e8 94 | 27-Apr-17,83,2017-04-27T12:27:31.000Z,2017-04-27T12:56:42.000Z,Manica,Manica,Bandula,Ruaca,17,yes,5,5,no,22,no,no,no,no,mabatisloping,burntbricks,NULL,earth,no,2,1,no,2,2,yes,NULL,2,yes,['Aug' ; 'Sept' ; 'Oct'],17,yes,no,NULL,yes,no,no,never,no,NULL,NULL,abt_half,no,no,['oxen' ; 'cows'],NULL,2,no,no,['radio' ; 'cow_plough' ; 'solar_torch'],NULL,2,['Aug' ; 'Sept' ; 'Oct'],['borrow_food' ; 'lab_ex_food'],-19.11231638,33.48349754,693,33,uuid:a1e9df00-c8ae-411c-931c-c7df898c68d0 95 | 27-Apr-17,85,2017-04-27T12:58:02.000Z,2017-04-27T13:23:06.000Z,Manica,Manica,Bandula,Ruaca,12,yes,7,7,no,40,yes,yes,yes,yes,grass,sunbricks,NULL,earth,no,3,1,no,3,3,yes,NULL,3,yes,['Sept' ; 'Oct'],12,yes,no,NULL,no,NULL,no,never,no,NULL,NULL,abt_half,yes,yes,['oxen' ; 'cows'],NULL,2,yes,no,['radio' ; 'cow_plough'],NULL,2,['Oct' ; 'Nov'],['na'],-19.11235114,33.48358508,697,10,uuid:4d0f472b-f8ae-4026-87c9-6b5be14b0a70 96 | 27-Apr-17,89,2017-04-27T16:11:23.000Z,2017-04-27T16:41:41.000Z,Manica,Manica,Bandula,God,10,no,5,5,no,10,yes,yes,no,yes,mabatisloping,burntbricks,NULL,cement,yes,2,2,yes,2,2,yes,NULL,2,yes,['Sept' ; 'Oct'],10,no,no,NULL,no,NULL,no,never,no,NULL,NULL,less_half,no,yes,['oxen' ; 'cows' ; 'goats'],NULL,3,no,no,['bicycle' ; 'radio' ; 'cow_plough' ; 'solar_panel' ; 'solar_torch' ; 'table' ; 'mobile_phone'],NULL,3,['Oct' ; 'Nov'],['rely_less_food' ; 'limit_variety' ; 'go_forest' ; 'lab_ex_food'],-19.11231667,33.48348329,710,13,uuid:b3b309c6-f234-4830-8b30-87d26a17ee1d 97 | 27-Apr-17,101,2017-04-27T16:42:02.000Z,2017-04-27T18:11:54.000Z,Manica,Manica,Bandula,God,10,no,3,3,no,4,yes,yes,no,no,grass,muddaub,NULL,earth,no,1,1,no,2,2,yes,NULL,2,yes,['Sept' ; 'Oct' ; 'Nov'],10,yes,no,NULL,no,NULL,no,never,no,NULL,NULL,abt_half,no,yes,['goats'],NULL,1,no,yes,['bicycle' ; 'solar_torch'],NULL,3,['Sept' ; 'Oct' ; 'Nov'],['rely_less_food' ; 'limit_variety' ; 'reduce_meals' ; 'restrict_adults' ; 'borrow_food' ; 'lab_ex_food'],-19.11223501,33.48341767,702,11,uuid:3c174acd-e431-4523-9ad6-eb14cddca805 98 | 27-Apr-17,103,2017-04-27T17:38:53.000Z,2017-04-27T18:09:45.000Z,Manica,Manica,Bandula,Ruaca,50,no,6,6,no,96,yes,yes,yes,yes,mabatisloping,sunbricks,NULL,earth,no,2,1,no,2,2,yes,NULL,2,yes,['Aug' ; 'Sept' ; 'Oct' ; 'Nov'],10,yes,no,NULL,no,NULL,no,never,no,NULL,NULL,less_half,yes,no,['oxen' ; 'cows' ; 'goats' ; 'pigs' ; 'poultry'],NULL,5,yes,no,['cow_cart' ; 'cow_plough' ; 'solar_panel' ; 'sofa_set' ; 'mobile_phone'],NULL,3,['Jan' ; 'Feb' ; 'Dec'],['go_forest'],-19.11219049,33.48337002,712,9,uuid:e9d79844-ef14-493b-bbd6-d13691cc660e 99 | 28-Apr-17,102,2017-04-28T06:27:07.000Z,2017-04-28T06:52:04.000Z,Manica,Manica,Bandula,Ruaca,15,yes,12,12,no,15,no,no,no,no,mabatisloping,burntbricks,NULL,earth,no,3,2,no,2,2,yes,NULL,2,yes,['Aug' ; 'Sept' ; 'Oct'],2,yes,no,NULL,yes,yes,no,frequently,no,NULL,NULL,less_half,no,yes,['cows' ; 'goats'],NULL,2,no,no,['cow_plough' ; 'table' ; 'sofa_set' ; 'mobile_phone'],NULL,3,['Jan' ; 'Feb'],['lab_ex_food'],-19.04413333,33.40388996,691,11,uuid:76206b0b-af74-4344-b24f-81e839f0d7b0 100 | 28-Apr-17,78,2017-04-28T07:09:39.000Z,2017-04-28T07:31:38.000Z,Manica,Manica,Bandula,Ruaca,20,no,6,6,no,48,yes,no,yes,no,mabatipitched,burntbricks,NULL,earth,no,2,1,no,2,2,yes,NULL,2,yes,['Aug' ; 'Sept'],20,yes,no,NULL,no,NULL,no,more_once,no,NULL,NULL,abt_half,no,no,['oxen' ; 'cows'],NULL,2,no,no,['cow_plough'],NULL,2,['Aug' ; 'Sept' ; 'Oct'],['na'],-19.04402591,33.40398184,723,11,uuid:da3fa7cc-5ce9-44fd-9a78-b8982b607515 101 | 28-Apr-17,80,2017-04-28T09:01:47.000Z,2017-04-28T09:25:51.000Z,Manica,Manica,Bandula,Ruaca,12,no,5,5,no,12,no,no,no,no,mabatipitched,muddaub,NULL,earth,no,1,1,no,1,1,yes,NULL,1,yes,['Sept' ; 'Oct' ; 'Nov'],12,yes,no,NULL,no,NULL,no,more_once,no,NULL,NULL,more_half,no,yes,['none'],NULL,1,yes,no,['cow_cart' ; 'bicycle' ; 'radio' ; 'cow_plough' ; 'solar_panel' ; 'solar_torch'],NULL,3,['none'],['na'],-19.04415001,33.40390046,689,6,uuid:a85df6df-0336-46fa-a9f4-522bf6f8b438 102 | 28-Apr-17,104,2017-04-28T14:25:13.000Z,2017-04-28T15:18:10.000Z,Manica,Manica,Bandula,Ruaca,35,no,14,14,no,52,yes,no,yes,no,grass,sunbricks,NULL,cement,no,4,1,yes,4,4,yes,NULL,4,yes,['Aug' ; 'Sept'],16,yes,no,NULL,yes,no,no,never,no,NULL,NULL,abt_half,no,no,['oxen' ; 'cows' ; 'goats' ; 'pigs'],NULL,4,yes,no,['cow_cart' ; 'bicycle' ; 'cow_plough'],NULL,3,['Jan' ; 'Feb' ; 'Dec'],['go_forest' ; 'lab_ex_food'],-19.11225606,33.4833734,711,9,uuid:bb2bb365-7d7d-4fe9-9353-b21269676119 103 | 28-Apr-17,105,2017-04-28T15:32:38.000Z,2017-04-28T15:58:10.000Z,Manica,Manica,Bandula,Ruaca,20,yes,6,6,no,40,yes,no,yes,no,mabatisloping,sunbricks,NULL,earth,no,2,1,no,2,2,yes,NULL,2,yes,['Aug' ; 'Sept' ; 'Oct' ; 'Nov'],1,yes,no,NULL,yes,yes,no,frequently,no,NULL,NULL,more_half,no,yes,['cows' ; 'poultry'],NULL,2,yes,yes,['motorcyle' ; 'radio' ; 'cow_plough' ; 'solar_panel' ; 'mobile_phone'],NULL,3,['Jan' ; 'Feb' ; 'Dec'],['lab_ex_food'],-19.11221203,33.48350526,735,11,uuid:af0904ee-4fdb-4090-973f-599c81ddf022 104 | 30-Apr-17,106,2017-04-30T05:51:18.000Z,2017-04-30T06:47:01.000Z,Manica,Manica,Bandula,God,22,yes,15,15,no,22,no,no,no,no,mabatisloping,sunbricks,NULL,cement,yes,4,5,yes,5,5,yes,NULL,5,yes,['Aug' ; 'Sept' ; 'Oct' ; 'Nov'],21,yes,no,NULL,no,NULL,no,never,no,NULL,NULL,more_half,yes,no,['oxen' ; 'cows'],NULL,2,yes,no,['cow_cart' ; 'motorcyle' ; 'bicycle' ; 'radio' ; 'sterio' ; 'cow_plough' ; 'solar_panel' ; 'solar_torch' ; 'table' ; 'mobile_phone'],NULL,3,['Oct' ; 'Nov' ; 'Dec'],['lab_ex_food' ; 'seek_government'],-19.11220965,33.48340866,709,5,uuid:468797c1-4a65-4f35-9c83-e28ce46972a2 105 | 3-May-17,109,2017-05-03T13:14:43.000Z,2017-05-03T13:37:53.000Z,Manica,Manica,Bandula,God,12,yes,4,4,no,12,yes,no,yes,no,grass,sunbricks,NULL,earth,no,1,1,yes,3,3,no,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,no,no,['oxen' ; 'cows' ; 'goats'],NULL,3,yes,no,['cow_cart' ; 'bicycle' ; 'radio' ; 'cow_plough' ; 'table'],NULL,3,['July' ; 'Aug' ; 'Sept' ; 'Oct' ; 'Nov'],['rely_less_food' ; 'limit_portion' ; 'reduce_meals'],-19.11222402,33.48338036,699,10,uuid:602cd3f6-4a97-49c6-80e3-bcfd5c78dfa4 106 | 3-May-17,110,2017-05-03T13:37:57.000Z,2017-05-03T13:58:06.000Z,Manica,Manica,Bandula,Ruaca,22,no,6,6,no,22,yes,yes,yes,yes,mabatisloping,sunbricks,NULL,cement,no,2,3,yes,3,3,yes,NULL,3,yes,['Aug' ; 'Sept' ; 'Oct' ; 'Nov'],22,yes,no,NULL,no,NULL,no,never,no,NULL,NULL,abt_half,no,no,['oxen' ; 'cows' ; 'goats'],NULL,3,yes,no,['bicycle' ; 'radio' ; 'cow_plough' ; 'table' ; 'mobile_phone'],NULL,2,['none'],['na'],-19.11219756,33.48339714,704,9,uuid:e7c51ac4-24e4-475e-88e7-f85e896945e3 107 | 3-May-17,113,2017-05-03T14:00:13.000Z,2017-05-03T14:27:03.000Z,Manica,Manica,Bandula,Ruaca,16,no,11,11,yes,26,yes,no,no,no,mabatisloping,burntbricks,NULL,cement,no,2,3,yes,3,3,yes,NULL,3,yes,['Sept' ; 'Oct'],2,yes,no,NULL,no,NULL,no,never,no,NULL,NULL,less_half,yes,no,['oxen' ; 'cows' ; 'goats' ; 'poultry'],NULL,4,no,no,['cow_cart' ; 'motorcyle' ; 'bicycle' ; 'radio' ; 'cow_plough' ; 'solar_panel' ; 'solar_torch' ; 'table' ; 'mobile_phone'],NULL,3,['none'],['na'],-19.11222682,33.48340708,706,12,uuid:01210861-aba1-4268-98d0-0260e05f5155 108 | 4-May-17,118,2017-05-04T10:26:35.000Z,2017-05-04T10:46:35.000Z,Manica,Manica,Bandula,Ruaca,6,no,5,5,no,25,yes,yes,yes,no,grass,muddaub,NULL,earth,no,2,1,no,1,1,no,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,no,yes,['none'],NULL,1,yes,no,['radio' ; 'solar_torch' ; 'mobile_phone'],NULL,3,['Oct' ; 'Nov' ; 'Dec'],['rely_less_food' ; 'limit_variety' ; 'reduce_meals' ; 'borrow_food' ; 'lab_ex_food'],-19.11220573,33.48344178,713,9,uuid:77335b2e-8812-4a35-b1e5-ca9ab626dfea 109 | 4-May-17,125,2017-05-04T10:47:05.000Z,2017-05-04T11:16:05.000Z,Manica,Manica,Bandula,Ruaca,7,yes,5,5,no,14,no,yes,no,yes,mabatisloping,burntbricks,NULL,earth,no,1,1,no,3,3,yes,NULL,3,yes,['Aug' ; 'Sept' ; 'Oct' ; 'Nov'],3,yes,yes,['less_work'],no,NULL,no,more_once,no,NULL,NULL,less_half,yes,yes,['oxen' ; 'cows'],NULL,2,no,yes,['bicycle' ; 'radio' ; 'cow_plough' ; 'solar_panel' ; 'solar_torch' ; 'mobile_phone'],NULL,3,['Jan' ; 'Sept' ; 'Oct' ; 'Nov' ; 'Dec'],['borrow_food' ; 'lab_ex_food'],-19.11218005,33.4834101,682,11,uuid:02b05c68-302e-4e7a-b229-81cb1377fd29 110 | 4-May-17,119,2017-05-04T11:16:57.000Z,2017-05-04T11:38:38.000Z,Manica,Manica,Bandula,Ruaca-Nhamuenda,14,no,3,3,yes,14,yes,no,no,no,grass,muddaub,NULL,earth,no,4,1,no,2,2,yes,NULL,2,no,NULL,3,yes,no,NULL,no,NULL,no,never,no,NULL,NULL,more_half,no,no,['oxen' ; 'cows' ; 'goats' ; 'poultry'],NULL,4,no,no,['bicycle' ; 'cow_plough' ; 'solar_panel' ; 'mobile_phone'],NULL,3,['none'],['na'],-19.11225658,33.48334839,706,5,uuid:fa201fce-4e94-44b8-b435-c558c2e1ed55 111 | 11-May-17,115,2017-05-11T05:24:25.000Z,2017-05-11T05:41:56.000Z,Manica,Manica,Bandula,Ruaca - Nhamuenda,16,no,4,4,no,16,yes,yes,no,no,mabatisloping,sunbricks,NULL,cement,no,3,2,yes,2,2,no,2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,yes,no,['oxen' ; 'cows' ; 'goats'],NULL,3,yes,no,['cow_cart' ; 'motorcyle' ; 'bicycle' ; 'television' ; 'radio' ; 'cow_plough' ; 'solar_panel' ; 'solar_torch' ; 'table' ; 'mobile_phone'],NULL,3,['none'],['na'],-19.1114691,33.4761047,0,20,uuid:628fe23d-188f-43e4-a203-a4bf3257d461 112 | 11-May-17,108,2017-05-11T05:42:08.000Z,2017-05-11T06:08:58.000Z,Manica,Manica,Bandula,God,22,no,15,15,no,22,no,yes,no,yes,mabatisloping,burntbricks,NULL,cement,no,3,2,yes,3,3,yes,NULL,3,yes,['Sept' ; 'Oct' ; 'Nov'],16,yes,no,NULL,no,NULL,no,never,no,NULL,NULL,abt_half,no,no,['oxen' ; 'cows' ; 'goats' ; 'poultry'],NULL,4,yes,no,['cow_cart' ; 'bicycle' ; 'radio' ; 'cow_plough' ; 'solar_panel' ; 'table' ; 'mobile_phone'],NULL,3,['Aug' ; 'Sept' ; 'Oct' ; 'Nov'],['rely_less_food' ; 'limit_portion' ; 'reduce_meals'],-19.1114691,33.4761047,0,20,uuid:e4f4d6ba-e698-45a5-947f-ba6da88cc22b 113 | 11-May-17,116,2017-05-11T06:09:56.000Z,2017-05-11T06:22:19.000Z,Manica,Manica,Bandula,Ruaca-Nhamuenda,21,yes,5,5,no,25,no,no,no,no,grass,burntbricks,NULL,cement,no,2,3,yes,1,1,no,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,no,yes,['oxen' ; 'cows' ; 'goats'],NULL,3,yes,no,['motorcyle' ; 'bicycle' ; 'television' ; 'radio' ; 'cow_plough' ; 'solar_panel' ; 'solar_torch' ; 'table' ; 'mobile_phone'],NULL,3,['Jan' ; 'Nov' ; 'Dec'],['rely_less_food' ; 'limit_variety' ; 'reduce_meals' ; 'lab_ex_food'],-19.1114691,33.4761047,0,20,uuid:cfee6297-2c0e-4f8a-94cc-9aaee0bd64cb 114 | 11-May-17,117,2017-05-11T06:28:02.000Z,2017-05-11T06:55:35.000Z,Manica,Manica,Bandula,Ruaca-Nhamuenda,1,no,10,10,no,28,yes,yes,yes,no,grass,muddaub,NULL,cement,no,1,4,no,1,1,no,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,no,yes,['none'],NULL,1,yes,no,['motorcyle' ; 'television' ; 'radio' ; 'solar_panel' ; 'solar_torch' ; 'table' ; 'mobile_phone'],NULL,3,['Jan' ; 'Feb' ; 'Nov' ; 'Dec'],['rely_less_food' ; 'limit_variety' ; 'reduce_meals' ; 'restrict_adults' ; 'borrow_food' ; 'lab_ex_food'],-19.1114691,33.4761047,0,20,uuid:3fe626b3-c794-48e1-a80f-5bfe440c507b 115 | 18-May-17,144,2017-05-18T04:36:23.000Z,2017-05-18T05:02:38.000Z,Manica,Manica,Bandula,Ruaca,5,no,7,7,no,5,yes,yes,yes,yes,mabatisloping,burntbricks,NULL,cement,no,3,4,no,2,2,yes,NULL,2,yes,['Sept' ; 'Oct' ; 'Nov'],5,yes,no,NULL,no,NULL,yes,frequently,yes,['farming'],NULL,abt_half,no,no,['oxen' ; 'cows' ; 'goats' ; 'sheep'],NULL,4,yes,no,['cow_cart' ; 'television' ; 'radio' ; 'cow_plough' ; 'solar_panel' ; 'solar_torch' ; 'table' ; 'mobile_phone'],NULL,2,['none'],['na'],-19.11218801,33.48342233,710,5,uuid:0670cef6-d233-4852-89d8-36955261b0a3 116 | 18-May-17,143,2017-05-18T05:55:04.000Z,2017-05-18T06:37:10.000Z,Manica,Manica,Bandula,Ruaca,24,yes,10,10,no,24,yes,no,no,no,grass,burntbricks,NULL,earth,no,3,2,yes,3,3,yes,NULL,3,yes,['Sept' ; 'Oct' ; 'Nov'],12,yes,no,NULL,no,NULL,no,frequently,no,NULL,NULL,more_half,yes,no,['oxen' ; 'cows' ; 'goats'],NULL,3,yes,no,['cow_cart' ; 'motorcyle' ; 'television' ; 'radio' ; 'cow_plough' ; 'solar_torch' ; 'table' ; 'mobile_phone'],NULL,3,['Jan' ; 'Dec'],['rely_less_food' ; 'limit_variety'],-19.1124845,33.4763322,0,1911,uuid:9a096a12-b335-468c-b3cc-1191180d62de 117 | 18-May-17,150,2017-05-18T10:37:37.000Z,2017-05-18T10:56:00.000Z,Manica,Manica,Bandula,Ruaca,8,no,7,7,no,8,no,yes,no,yes,grass,muddaub,NULL,earth,no,2,1,no,2,2,yes,NULL,2,yes,['Apr' ; 'May' ; 'June' ; 'July' ; 'Aug' ; 'Sept' ; 'Oct' ; 'Nov'],8,yes,no,NULL,no,NULL,no,never,no,NULL,NULL,less_half,no,yes,['cows'],NULL,1,no,yes,['mobile_phone'],NULL,3,['Sept' ; 'Oct' ; 'Nov'],['reduce_meals' ; 'lab_ex_food'],-19.11147739,33.47618369,709,17,uuid:92613d0d-e7b1-4d62-8ea4-451d7cd0a982 118 | 18-May-17,159,2017-05-18T10:56:16.000Z,2017-05-18T11:07:35.000Z,Manica,Manica,Bandula,God,17,yes,4,4,no,24,yes,no,yes,no,grass,sunbricks,NULL,earth,no,2,1,no,2,2,yes,NULL,2,no,NULL,2,yes,no,NULL,no,NULL,no,never,no,NULL,NULL,less_half,no,yes,['none'],NULL,1,no,no,['radio' ; 'solar_panel' ; 'solar_torch'],NULL,3,['Sept' ; 'Oct' ; 'Nov'],['lab_ex_food'],-19.11149498,33.47617506,712,28,uuid:37577f91-d665-443e-8d70-b914954cef4b 119 | 3-Jun-17,160,2017-06-03T05:08:49.000Z,2017-06-03T05:32:19.000Z,Manica,Manica,Bandula,God,3,yes,7,7,no,13,yes,yes,yes,yes,mabatisloping,burntbricks,NULL,earth,no,2,2,no,3,3,yes,NULL,3,yes,['Jan' ; 'Dec'],3,yes,no,NULL,yes,yes,no,frequently,no,NULL,NULL,more_half,yes,yes,['oxen' ; 'cows'],NULL,2,yes,no,['cow_cart' ; 'cow_plough' ; 'solar_torch' ; 'mobile_phone'],NULL,2,['Nov'],['lab_ex_food'],-19.11218456,33.4834495,711,12,uuid:f22831ec-6bc3-4b73-9197-4b01e01abb66 120 | 3-Jun-17,165,2017-06-03T05:32:33.000Z,2017-06-03T05:51:49.000Z,Manica,Manica,Bandula,Ruaca,14,no,9,9,no,14,no,no,no,no,grass,burntbricks,NULL,earth,no,1,1,yes,2,2,yes,NULL,2,yes,['Aug' ; 'Sept' ; 'Oct' ; 'Nov' ; 'Dec'],10,yes,no,NULL,no,NULL,no,never,no,NULL,NULL,less_half,no,no,['oxen' ; 'cows' ; 'goats'],NULL,3,yes,no,['cow_cart' ; 'motorcyle' ; 'bicycle' ; 'television' ; 'radio' ; 'cow_plough' ; 'solar_torch' ; 'electricity' ; 'table' ; 'sofa_set' ; 'mobile_phone' ; 'fridge'],NULL,3,['none'],['na'],-19.11217437,33.48346513,708,9,uuid:62f3f7af-f0f3-4f88-b9e0-acf8baa49ae4 121 | 3-Jun-17,166,2017-06-03T05:53:28.000Z,2017-06-03T06:25:06.000Z,Manica,Manica,Bandula,Ruaca,16,no,11,11,no,16,yes,yes,yes,yes,grass,muddaub,NULL,earth,no,2,1,no,3,3,yes,NULL,3,yes,['Aug' ; 'Sept' ; 'Oct'],2,yes,no,NULL,no,NULL,no,never,no,NULL,NULL,less_half,no,yes,['goats'],NULL,1,yes,no,['bicycle' ; 'solar_torch' ; 'mobile_phone'],NULL,2,['Feb' ; 'Mar'],['go_forest' ; 'lab_ex_food'],-19.1138589,33.4826653,0,1799.999,uuid:40aac732-94df-496c-97ba-5b67f59bcc7a 122 | 3-Jun-17,167,2017-06-03T06:25:09.000Z,2017-06-03T06:45:06.000Z,Manica,Manica,Bandula,Ruaca,16,no,8,8,no,24,yes,no,yes,no,grass,muddaub,NULL,earth,no,5,1,no,2,2,yes,NULL,2,yes,['July' ; 'Aug' ; 'Sept' ; 'Oct' ; 'Nov' ; 'Dec'],16,yes,no,NULL,no,NULL,no,never,no,NULL,NULL,less_half,no,yes,['oxen' ; 'cows' ; 'goats'],NULL,3,yes,yes,['motorcyle' ; 'radio' ; 'cow_plough' ; 'solar_panel' ; 'solar_torch' ; 'table' ; 'mobile_phone'],NULL,2,['Jan' ; 'Nov' ; 'Dec'],['lab_ex_food'],-19.1149887,33.4882685,0,2000,uuid:a9d1a013-043b-475d-a71b-77ed80abe970 123 | 3-Jun-17,174,2017-06-03T06:50:47.000Z,2017-06-03T07:20:21.000Z,Manica,Manica,Bandula,Ruaca,13,no,12,12,no,25,yes,yes,yes,yes,grass,burntbricks,NULL,cement,no,2,2,yes,3,3,yes,NULL,3,yes,['Sept' ; 'Oct' ; 'Nov' ; 'Dec'],13,yes,yes,['cheaper'],no,NULL,no,never,no,NULL,NULL,more_half,yes,no,['oxen' ; 'cows' ; 'goats'],NULL,3,yes,no,['car' ; 'lorry' ; 'motorcyle' ; 'radio' ; 'sterio' ; 'cow_plough' ; 'solar_panel' ; 'solar_torch' ; 'table' ; 'sofa_set' ; 'mobile_phone' ; 'fridge'],NULL,3,['Jan' ; 'Feb' ; 'Dec'],['lab_ex_food'],-19.11216751,33.48340539,703,3,uuid:43ec6132-478c-4f87-878d-fb3c0c4d0c74 124 | 3-Jun-17,175,2017-06-03T07:21:48.000Z,2017-06-03T07:51:29.000Z,Manica,Manica,Bandula,Ruaca,11,no,7,7,no,36,yes,yes,yes,yes,mabatisloping,burntbricks,NULL,earth,no,2,1,no,2,2,yes,NULL,2,yes,['Oct' ; 'Nov'],11,yes,no,NULL,no,NULL,no,never,no,NULL,NULL,more_half,no,no,['oxen' ; 'cows' ; 'goats' ; 'poultry'],NULL,4,yes,yes,['motorcyle' ; 'bicycle' ; 'radio' ; 'sterio' ; 'cow_plough' ; 'solar_panel' ; 'table' ; 'mobile_phone'],NULL,2,['Jan' ; 'Oct' ; 'Nov' ; 'Dec'],['na'],-19.11217963,33.48336019,705,5,uuid:64fc743e-8176-40f6-8ae4-36ae97fac1d9 125 | 3-Jun-17,189,2017-06-03T15:23:01.000Z,2017-06-03T15:53:10.000Z,Manica,Manica,Bandula,Ruaca,10,yes,15,15,no,16,no,yes,no,yes,mabatisloping,sunbricks,NULL,earth,no,2,1,yes,3,3,yes,NULL,3,yes,['Aug' ; 'Sept' ; 'Oct' ; 'Nov' ; 'Dec'],7,yes,no,NULL,no,NULL,no,never,no,NULL,NULL,more_half,no,yes,['oxen' ; 'cows' ; 'goats'],NULL,3,yes,no,['motorcyle' ; 'radio' ; 'sterio' ; 'cow_plough' ; 'solar_panel' ; 'table' ; 'mobile_phone'],NULL,3,['Nov'],['na'],-19.11216796,33.48341529,714,4,uuid:c17e374c-280b-4e78-bf21-74a7c1c73492 126 | 3-Jun-17,191,2017-06-03T15:54:03.000Z,2017-06-03T16:17:26.000Z,Manica,Manica,Bandula,Ruaca,3,no,10,10,no,5,yes,no,yes,no,mabatisloping,burntbricks,NULL,cement,yes,1,4,yes,2,2,yes,NULL,2,yes,['Sept' ; 'Oct' ; 'Nov'],3,yes,no,NULL,no,NULL,no,never,no,NULL,NULL,abt_half,no,no,['cows'],NULL,1,yes,no,['radio' ; 'cow_plough' ; 'solar_panel' ; 'solar_torch' ; 'mobile_phone'],NULL,2,['Oct' ; 'Nov' ; 'Dec'],['go_forest' ; 'lab_ex_food'],-19.11219207,33.48338051,709,9,uuid:dad53aff-b520-4015-a9e3-f5fdf9168fe1 127 | 3-Jun-17,192,2017-06-03T16:17:55.000Z,2017-06-03T17:16:39.000Z,Manica,Manica,Bandula,Chirodzo,15,yes,9,9,no,20,yes,yes,yes,yes,grass,burntbricks,NULL,cement,yes,4,1,no,3,3,yes,NULL,3,yes,['Sept' ; 'Nov'],5,yes,no,NULL,no,NULL,no,once,no,NULL,NULL,more_half,yes,yes,['none'],NULL,1,yes,no,['bicycle' ; 'television' ; 'radio' ; 'sterio' ; 'solar_panel' ; 'solar_torch' ; 'table' ; 'mobile_phone'],NULL,3,['Jan' ; 'Nov' ; 'Dec'],['borrow_food'],-19.11215404,33.48335905,705,4,uuid:f94409a6-e461-4e4c-a6fb-0072d3d58b00 128 | 18-May-17,126,2017-05-18T04:13:37.000Z,2017-05-18T04:35:47.000Z,Manica,Manica,Bandula,Ruaca,5,yes,3,3,no,7,yes,yes,yes,yes,grass,burntbricks,NULL,earth,no,1,1,no,2,2,yes,NULL,2,yes,['Sept' ; 'Oct' ; 'Nov'],4,yes,no,NULL,no,NULL,no,more_once,no,NULL,NULL,less_half,yes,yes,['oxen' ; 'cows' ; 'goats'],NULL,3,yes,no,['motorcyle' ; 'radio' ; 'solar_panel'],NULL,3,['Oct' ; 'Nov' ; 'Dec'],['rely_less_food' ; 'lab_ex_food'],-19.11219355,33.48337856,700,7,uuid:69caea81-a4e5-4e8d-83cd-9c18d8e8d965 129 | 4-Jun-17,193,2017-06-04T09:36:20.000Z,2017-06-04T10:13:32.000Z,Manica,Manica,Bandula,Ruaca,10,no,7,7,no,10,no,no,no,no,mabatisloping,cement,NULL,cement,yes,3,3,yes,4,4,yes,NULL,4,yes,['Oct' ; 'Nov' ; 'Dec'],10,yes,no,NULL,no,NULL,no,more_once,no,NULL,NULL,more_half,no,yes,['oxen' ; 'cows' ; 'goats'],NULL,3,no,no,['car' ; 'lorry' ; 'television' ; 'radio' ; 'sterio' ; 'cow_plough' ; 'solar_torch' ; 'electricity' ; 'table' ; 'sofa_set' ; 'mobile_phone' ; 'fridge'],NULL,3,['none'],['na'],-19.11215668,33.48339039,720,9,uuid:5ccc2e5a-ea90-48b5-8542-69400d5334df 130 | 4-Jun-17,194,2017-06-04T10:13:36.000Z,2017-06-04T10:32:06.000Z,Manica,Manica,Bandula,Ruaca,5,no,4,4,no,5,no,no,yes,no,grass,muddaub,NULL,earth,no,2,1,no,2,2,yes,NULL,2,yes,['Aug' ; 'Sept' ; 'Oct'],2,yes,no,NULL,no,NULL,no,more_once,no,NULL,NULL,more_half,no,yes,['poultry'],NULL,1,no,no,['radio' ; 'solar_panel' ; 'solar_torch' ; 'mobile_phone'],NULL,3,['Sept' ; 'Oct' ; 'Nov'],['lab_ex_food'],-19.11227133,33.48347111,719,10,uuid:95c11a30-d44f-40c4-8ea8-ec34fca6bbbf 131 | 4-Jun-17,199,2017-06-04T10:33:55.000Z,2017-06-04T10:52:22.000Z,Manica,Manica,Bandula,Chirodzo,17,yes,7,7,no,17,no,no,no,no,mabatisloping,burntbricks,NULL,cement,yes,1,2,no,2,2,yes,NULL,2,yes,['Sept' ; 'Oct' ; 'Nov'],6,yes,no,NULL,yes,yes,no,more_once,yes,['farming' ; 'business'],NULL,more_half,yes,no,['oxen' ; 'cows'],NULL,2,yes,no,['cow_cart' ; 'lorry' ; 'motorcyle' ; 'computer' ; 'television' ; 'radio' ; 'sterio' ; 'cow_plough' ; 'solar_panel' ; 'solar_torch' ; 'electricity' ; 'mobile_phone'],NULL,3,['Nov' ; 'Dec'],['rely_less_food' ; 'limit_variety' ; 'reduce_meals' ; 'restrict_adults' ; 'lab_ex_food'],-19.11227751,33.48338952,711,5,uuid:ffc83162-ff24-4a87-8709-eff17abc0b3b 132 | 4-Jun-17,200,2017-06-04T10:52:46.000Z,2017-06-04T11:08:13.000Z,Manica,Manica,Bandula,Chirodzo,20,yes,8,8,no,20,no,yes,no,yes,mabatisloping,burntbricks,NULL,cement,no,1,2,yes,2,2,no,2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,no,yes,['oxen' ; 'goats' ; 'pigs'],NULL,3,yes,no,['radio' ; 'cow_plough' ; 'solar_panel' ; 'solar_torch' ; 'table' ; 'mobile_phone'],NULL,3,['Oct' ; 'Nov'],['rely_less_food' ; 'restrict_adults' ; 'borrow_food'],-19.11218302,33.48337175,681,20,uuid:aa77a0d7-7142-41c8-b494-483a5b68d8a7 -------------------------------------------------------------------------------- /files/setup-data.md: -------------------------------------------------------------------------------- 1 | --- 2 | ~ 3 | --- 4 | 5 | ## Data 6 | 7 | You can [download all of the data used in this workshop](https://ndownloader.figshare.com/articles/6262019/versions/4) 8 | as a single zip file. The file is 206 KB. 9 | 10 | Clicking the download link will automatically download all of the files to your default download directory as a single compressed 11 | (`.zip`) file. To expand this file, double click the folder icon in your file navigator application (for Macs, this is the Finder 12 | application). 13 | 14 | For a full description of the data used in this workshop see the [data page](data). 15 | 16 | 17 | -------------------------------------------------------------------------------- /files/setup-openrefine.md: -------------------------------------------------------------------------------- 1 | --- 2 | ~ 3 | --- 4 | 5 | ### OpenRefine 6 | 7 | OpenRefine can be downloaded from the [OpenRefine downloads]() page. 8 | When you download the version for your operating system, you are redirected to 9 | a page with initial instructions for running the software. 10 | 11 | More detailed instructions are included in the [Setup section in the OpenRefine 12 | for Social Science Data](https://datacarpentry.org/openrefine-socialsci/#software). 13 | 14 | 15 | -------------------------------------------------------------------------------- /files/setup-overview.md: -------------------------------------------------------------------------------- 1 | --- 2 | ~ 3 | --- 4 | 5 | # Overview 6 | 7 | This workshop is designed to be run on your laptop. 8 | First, you will need to download the data we use in the workshop. 9 | Then, you need to install some software. 10 | After following the instructions on this 11 | page, you should have everything you need to participate fully in the workshop! 12 | 13 | 14 | -------------------------------------------------------------------------------- /files/setup-python.md: -------------------------------------------------------------------------------- 1 | --- 2 | ~ 3 | --- 4 | 5 | ### Python and Jupyter Notebooks 6 | 7 | [Python](https://python.org) is a popular language for scientific computing, and great for general-purpose programming as well. 8 | For this workshop we use Python version 3.x. 9 | Installing all of its scientific packages individually can be a bit difficult, so we provide an environment file to help you take care of them all together. 10 | We will use the _Miniforge_ distribution of Python. 11 | 12 | Please refer to the [Python section of the workshop website for installation instructions](https://carpentries.github.io/workshop-template/install_instructions/#python). 13 | 14 | #### Launching Jupyter 15 | 16 | :::::::::::::::::::::::::::::::::::::::::: spoiler 17 | 18 | ##### Windows 19 | 20 | After following the instructions above, search for the application 'Miniforge Prompt' and open it. 21 | Type the following commands, pressing Enter after each one: 22 | 23 | ```bash 24 | conda activate carpentries 25 | jupyter notebook 26 | ``` 27 | 28 | :::::::::::::::::::::::::::::::::::::::::::::::::: 29 | 30 | :::::::::::::::::::::::::::::::::::::::::: spoiler 31 | 32 | ##### MacOS 33 | 34 | After following the instructions above, open the Terminal application (inside Applications/Utilities). 35 | Type the following commands, pressing Enter after each one: 36 | 37 | ```bash 38 | conda activate carpentries 39 | jupyter notebook 40 | ``` 41 | :::::::::::::::::::::::::::::::::::::::::::::::::: 42 | 43 | :::::::::::::::::::::::::::::::::::::::::: spoiler 44 | 45 | ##### Linux 46 | 47 | After following the instructions above, search for the application 'Miniforge Prompt' and open it. 48 | Type the following commands, pressing Enter after each one: 49 | 50 | ```bash 51 | conda activate carpentries 52 | jupyter notebook 53 | ``` 54 | 55 | :::::::::::::::::::::::::::::::::::::::::::::::::: 56 | 57 | The notebook should open automatically in your browser. 58 | If it does not or you wish to use a different browser, open this link: [http://localhost:8888](https://localhost:8888). 59 | 60 | For a brief introduction to Jupyter Notebooks, please consult our 61 | [Introduction to Jupyter Notebooks](https://datacarpentry.org/python-ecology-lesson/jupyter_notebooks/) page. -------------------------------------------------------------------------------- /files/setup-r.md: -------------------------------------------------------------------------------- 1 | --- 2 | ~ 3 | --- 4 | 5 | ### R and RStudio 6 | 7 | - R and RStudio are separate downloads and installations. R is the 8 | underlying statistical computing environment, but using R alone is no 9 | fun. RStudio is a graphical integrated development environment (IDE) that makes 10 | using R much easier and more interactive. You need to install R before you 11 | install RStudio. After installing both programs, you will need to install 12 | some specific R packages within RStudio. Follow the instructions below for 13 | your operating system, and then follow the instructions to install 14 | **`tidyverse`** and **`RSQLite`**. 15 | 16 | #### Windows 17 | 18 | :::::::::::::::: spoiler 19 | 20 | ## If you already have R and RStudio installed 21 | 22 | - Open RStudio, and click on "Help" > "Check for updates". If a new version is 23 | available, quit RStudio, and download the latest version for RStudio. 24 | - To check which version of R you are using, start RStudio and the first thing 25 | that appears in the console indicates the version of R you are 26 | running. Alternatively, you can type `sessionInfo()`, which will also display 27 | which version of R you are running. Go on 28 | the [CRAN website](https://cran.r-project.org/bin/windows/base/) and check 29 | whether a more recent version is available. If so, please download and install 30 | it. 31 | 32 | You can [uninstall older versions of R][uninstall-r] if you wish to do so. 33 | 34 | 35 | ::::::::::::::::::::::::: 36 | 37 | :::::::::::::::: spoiler 38 | 39 | ## If you don't have R and RStudio installed 40 | 41 | - Download R from 42 | the [CRAN website](https://cran.r-project.org/bin/windows/base/release.htm). 43 | - Run the `.exe` file that was just downloaded 44 | - Go to the [RStudio download page][download-rstudio] 45 | - Under *Installers* select **RStudio x.yy.zzz - Windows Vista/7/8/10** (where x, y, and z represent version numbers) 46 | - Double click the file to install it 47 | - Once it's installed, open RStudio to make sure it works and you don't get any 48 | error messages. 49 | 50 | 51 | ::::::::::::::::::::::::: 52 | 53 | #### macOS 54 | 55 | :::::::::::::::: spoiler 56 | 57 | ## If you already have R and RStudio installed 58 | 59 | - Open RStudio, and click on "Help" > "Check for updates". If a new version is 60 | available, quit RStudio, and download the latest version for RStudio. 61 | - To check the version of R you are using, start RStudio and the first thing 62 | that appears on the terminal indicates the version of R you are running. Alternatively, you can type `sessionInfo()`, which will 63 | also display which version of R you are running. Go on 64 | the [CRAN website](https://cran.r-project.org/bin/macosx/) and check 65 | whether a more recent version is available. If so, please download and install 66 | it. In any case, make sure you have at least R 3.2. 67 | 68 | 69 | ::::::::::::::::::::::::: 70 | 71 | :::::::::::::::: spoiler 72 | 73 | ## If you don't have R and RStudio installed 74 | 75 | - Download R from 76 | the [CRAN website](https://cran.r-project.org/bin/macosx/). 77 | - Select the `.pkg` file for the latest R version 78 | - Double click on the downloaded file to install R 79 | - It is also a good idea to install [XQuartz](https://www.xquartz.org/) (needed 80 | by some packages) 81 | - Go to the [RStudio download page][download-rstudio] 82 | - Under *Installers* select **RStudio x.yy.zzz - Mac OS X 10.6+ (64-bit)** 83 | (where x, y, and z represent version numbers) 84 | - Double click the file to install RStudio 85 | - Once it's installed, open RStudio to make sure it works and you don't get any 86 | error messages. 87 | 88 | 89 | ::::::::::::::::::::::::: 90 | 91 | #### Linux 92 | 93 | - Follow the instructions for your distribution 94 | from [CRAN](https://cloud.r-project.org/bin/linux), they provide information 95 | to get the most recent version of R for common distributions. For most 96 | distributions, you could use your package manager (e.g., for Debian/Ubuntu run 97 | `sudo apt-get install r-base`, and for Fedora `sudo yum install R`), but we 98 | don't recommend this approach as the versions provided by this are 99 | usually out of date. In any case, make sure you have at least R 3.2. 100 | 101 | - Go to the [RStudio download page][download-rstudio] 102 | 103 | - Under *Installers* select the version that matches your distribution, and 104 | install it with your preferred method (e.g., with Debian/Ubuntu `sudo dpkg -i rstudio-x.yy.zzz-amd64.deb` at the terminal). 105 | 106 | - Once it's installed, open RStudio to make sure it works and you don't get any 107 | error messages. 108 | 109 | - After installing R and RStudio, you need to install the `tidyverse` and 110 | `RSQLite` packages. Start RStudio by double-clicking the icon and then type: 111 | `install.packages(c("tidyverse", "RSQLite"))`. You can also do this by going to Tools -> Install Packages and 112 | typing the names of the packages you want to install, separated by a comma. 113 | 114 | [uninstall-r]: https://cran.r-project.org/bin/windows/base/rw-FAQ.html#How-do-I-UNinstall-R_003f 115 | [download-rstudio]: https://posit.co/download/rstudio-desktop/#download 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /files/setup-spreadsheet.md: -------------------------------------------------------------------------------- 1 | --- 2 | ~ 3 | --- 4 | 5 | ### Spreadsheet program 6 | 7 | - To interact with spreadsheets, we can use LibreOffice, Microsoft Excel, Gnumeric, OpenOffice.org, or other programs. 8 | Commands may differ a bit between programs, but the general ideas for thinking about spreadsheets are the same. For this workshop, 9 | we recommend using either Microsoft Excel (paid software) or LibreOffice (free and open source). Other spreadsheet programs may 10 | not have all of the features we will be exploring in this workshop. 11 | 12 | - To install LibreOffice, first [download LibreOffice](https://www.libreoffice.org/download/download-libreoffice/). The website should 13 | automatically select the correct option for your operating system. Click the "Download" button. You will go to a page that asks about a 14 | donation, but you don't need to make one. Your download should begin automatically. Once the installer is downloaded, double click on it (you may need to open your Downloads folder) and LibreOffice should install. 15 | 16 | 17 | -------------------------------------------------------------------------------- /files/setup-sql.md: -------------------------------------------------------------------------------- 1 | --- 2 | ~ 3 | --- 4 | 5 | ## SQL 6 | 7 | - SQL is a specialized programming language used with databases. We 8 | use a simple database manager called [SQLite](https://www.sqlite.org/) 9 | in our lessons. We will use the [DB Browser for SQLite](https://sqlitebrowser.org/) program, 10 | which is available for all major platforms. 11 | 12 | - To install the DB Browser, first [download DB Browser for SQLite](https://sqlitebrowser.org/dl/) and choose the correct installer for 13 | your operating system. Once the installer is downloaded, double click on it (you may need to open your Downloads folder), follow 14 | any other instructions that appear, and 15 | DB Browser should install. After installing, you can delete the installer file. 16 | 17 | 18 | -------------------------------------------------------------------------------- /index.md: -------------------------------------------------------------------------------- 1 | --- 2 | site: sandpaper::sandpaper_site 3 | --- 4 | 5 | Data Carpentry's aim is to teach researchers basic concepts, skills, and tools 6 | for working with data so that they can get more done in less time, and with less 7 | pain. This workshop teaches data management and analysis for social science 8 | research including best practices for data organization in spreadsheets, 9 | reproducible data cleaning with OpenRefine, and data analysis and visualization 10 | in R. This curriculum is designed to be taught over two full days of instruction. 11 | 12 | Materials for teaching data analysis and visualization in Python 13 | and extraction of information from relational databases using SQL are in development. 14 | 15 | Interested in teaching these materials? 16 | We have an [onboarding video](https://www.youtube.com/watch?v=u4nDomxRVoI&t=2s) and accompanying 17 | [slides](https://docs.google.com/presentation/d/1rR7pLSftBYBnLBmaMWeytfDtcRfwVUWxPYGx30ZJNkc/edit#slide=id.p) 18 | available to prepare Instructors to teach these lessons. After watching this video, 19 | please contact [team@carpentries.org](mailto:team@carpentries.org) so that we can record your 20 | status as an onboarded Instructor. Instructors who 21 | have completed onboarding will be given priority status for teaching at centrally-organized 22 | Data Carpentry Social Sciences workshops. 23 | 24 | :::::::::::::::::::::::::::::::::::::::::: prereq 25 | 26 | ## Getting Started 27 | 28 | Data Carpentry's teaching is hands-on, so participants are encouraged to use 29 | their own computers to ensure the proper setup of tools for an efficient 30 | workflow. To most effectively use these materials, please make sure to download 31 | the data and install everything before working through this lesson. 32 | 33 | This workshop assumes no prior experience with the tools covered in the workshop. 34 | 35 | To get started, follow the directions in the [Setup](learners/setup.md) tab to 36 | get access to the required software and data for this workshop. 37 | 38 | :::::::::::::::::::::::::::::::::::::::::::::::::: 39 | 40 | :::::::::::::::::::::::::::::::::::::::::: prereq 41 | 42 | ## Data 43 | 44 | The data for this workshop are in the [SAFI Survey Results Project](https://doi.org/10.6084/m9.figshare.6262019.v4) 45 | available on FigShare, with a CC-BY license available for reuse. 46 | 47 | The [SAFI Project](https://www.safi-research.org/) is a research project 48 | looking at farming and irrigation methods used by farmers in Tanzania and 49 | Mozambique. This dataset is composed of survey data relating to households and 50 | agriculture in Tanzania and Mozambique. The survey form was created using the 51 | ODK (Open Data Kit) software via an Excel spreadsheet. This is used to create 52 | a form which can be downloaded and displayed (and completed) on an Android 53 | smartphone. The results are then sent back to a central server. The server can 54 | be used to produce the collected data in both JSON and CSV formats. We will 55 | use a sample of the collected data in CSV format throughout this workshop. 56 | 57 | [More information on this dataset](learners/data.md) 58 | 59 | :::::::::::::::::::::::::::::::::::::::::::::::::: 60 | 61 | This curriculum is currently available using R as the main programming language. Materials for teaching it with Python are in development. 62 | 63 | # Workshop Overview 64 | 65 | | Lesson | Overview | 66 | | ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ | 67 | | [Data Organization in Spreadsheets](https://datacarpentry.github.io/spreadsheets-socialsci/) | Learn how to organize tabular data, handle date formatting, carry out quality control and quality assurance and export data to use with downstream applications. | 68 | | [Data Cleaning with OpenRefine](https://datacarpentry.github.iog/openrefine-socialsci/) | Explore, summarize, and clean tabular data reproducibly. | 69 | | [Data Analysis and Visualisation with R](https://datacarpentry.github.io/r-socialsci) | Import data into R, calculate summary statistics, and create publication-quality graphics. | 70 | 71 | # Workshop Materials in Development 72 | 73 | | Lesson | Overview | 74 | | ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ | 75 | | [Data Analysis and Visualisation with Python](https://datacarpentry.github.io/python-socialsci/) | Import data into Python, calculate summary statistics, and create publication-quality graphics. | 76 | | [Data Management with SQL](https://datacarpentry.github.io/sql-socialsci/) | Extract information from relational databases. | 77 | 78 | 79 | -------------------------------------------------------------------------------- /instructors/instructor-notes.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Instructor Notes 3 | --- 4 | 5 | ## Workshop Structure 6 | 7 | The following table provides links to instructor notes and timings for each lesson in the Social Sciences Workshop. 8 | 9 | | Lesson | Link to Instructor Notes | Length | 10 | | ------ | ------------------------ | ------ | 11 | | [Data Organization in Spreadsheets for Social Scientists](https://datacarpentry.org/spreadsheets-socialsci/) | [Notes](https://datacarpentry.org/spreadsheets-socialsciinstructor/instructor-notes.html) | **2 hours** | 12 | | [Data Cleaning with Open Refine](https://datacarpentry.org/openrefine-socialsci/) | [Notes](https://datacarpentry.org/openrefine-socialsciinstructor/instructor-notes.html) | **2 hours** | 13 | | [Data Analysis and Visualization in R](https://datacarpentry.org/r-socialsci/) | [Notes](https://datacarpentry.org/r-socialsciinstructor/instructor-notes.html) | **6\.5 hours** | 14 | 15 | The following workshops are under development: 16 | 17 | | Lesson | Link to Instructor Notes | Length | 18 | | ------ | ------------------------ | ------ | 19 | | [Data Management with SQL for Social Scientists \*alpha\*](https://datacarpentry.org/sql-socialsci/) | \-- | **3\.5 hours** | 20 | | [Data Analysis and Visualization with Python for Social Scientists \*alpha\*](https://datacarpentry.org/python-socialsci/) | \-- | **9 hours** | 21 | 22 | [Instructors: add information about timing and selecting materials as these workshops are piloted] 23 | 24 | ## Technical tips and tricks 25 | 26 | #### Installation 27 | 28 | See [Setup](../learners/setup.md) section of this Workshop Overview. 29 | 30 | [Instructors: add information about supporting learners with various installations here] 31 | 32 | ## Common problems 33 | 34 | 35 | -------------------------------------------------------------------------------- /learners/data.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Workshop data 3 | permalink: /data/ 4 | --- 5 | 6 | All of the social science lessons use the same data set throughout. 7 | The data is tabular (rows and columns), similar in structure to what 8 | you might have in a spreadsheet. 9 | 10 | ## The SAFI Teaching Database 11 | 12 | Available on FigShare: [https://figshare.com/articles/SAFI\_Survey\_Results/6262019](https://figshare.com/articles/SAFI_Survey_Results/6262019) 13 | 14 | **CITATION:** Woodhouse, Philip; Veldwisch, Gert Jan; Brockington, Daniel; Komakech, Hans C.; Manjichi, Angela; Venot, Jean-Philippe (2018): SAFI Survey Results. doi:10.6084/m9.figshare.6262019.v1 15 | 16 | SAFI (Studying African Farmer-Led Irrigation) is a currently running 17 | project which is looking at farming and irrigation methods. This is 18 | survey data relating to households and agriculture in Tanzania and 19 | Mozambique. The survey data was collected through interviews 20 | conducted between November 2016 and June 2017 using forms downloaded 21 | to Android Smartphones. The survey forms were created using the ODK 22 | (Open Data Kit) software via an Excel spreadsheet. The collected data 23 | is then sent back to a central server. The server can be used to 24 | download the collected data in both JSON and CSV formats. This is a 25 | teaching version of the collected data that we will be using. It is not the full dataset. 26 | 27 | The survey covered such things as; household features (e.g. 28 | construction materials used, number of household members), 29 | agricultural practices (e.g. water usage), assets (e.g. number and 30 | types of livestock) and details about the household members. 31 | 32 | The basic teaching dataset used in these lessons is a JSON 33 | formatted dataset which is used directly in the Python lesson. For 34 | the other lessons a subset of the JSON dataset is used and has been 35 | converted into CSV format. 36 | 37 | The individual fields and the survey questions asked to produce the 38 | data in the CSV formatted version are given below. We will only 39 | reference a subset of the fields in the lessons. 40 | 41 | | column\_name | description | 42 | | -------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | 43 | | key\_id | Added to provide a unique Id for each observation. (The InstanceID field does this as well but it is not as convenient to use) | 44 | | interview\_date | Date of interview | 45 | | quest\_no | Questionnaire number | 46 | | start | Timestamp of start of interview | 47 | | end | Timestamp of end of interview | 48 | | province | Province name | 49 | | district | District name | 50 | | ward | Ward name | 51 | | village | Village name | 52 | | years\_farm | Number of years the household have been farming in this area | 53 | | agr\_assoc | Does the head of the household belong to an agricultural association? | 54 | | no\_membrs | How many members in the household? | 55 | | \_members\_count | Internal count of members | 56 | | remittance\_money | Is there any financial assistance from family members not living on the farm | 57 | | years\_liv | How many years have you been living in this village or neighboring village? | 58 | | parents\_liv | Did your parents live in this village or neighboring village? | 59 | | sp\_parents\_liv | Did your spouse's parents live in this village or neighbouring village? | 60 | | grand\_liv | Did your grandparents live in this village or neighbouring village? | 61 | | sp\_grand\_liv | Did your spouse's grandparents live in this village or neighbouring village? | 62 | | respondent\_roof\_type | What type of roof does their house have? | 63 | | respondent\_wall\_type | What type of walls does their house have (from list) | 64 | | respondent\_wall\_type\_other | What type of walls does their house have (not on list) | 65 | | respondent\_floor\_type | What type of floor does their house have | 66 | | window\_type | Does the house have glass in at least one window? | 67 | | buildings\_in\_compound | How many buildings are in the compound? Do not include stores, toilets or temporary structures. | 68 | | rooms | How many rooms in the main house are used for sleeping? | 69 | | other\_buildings | Does the DU own any other buildings other than those on this plot | 70 | | no\_plots | How many plots were cultivated in the last 12 months? | 71 | | plots\_count | Internal count of plots | 72 | | water\_use | Do you bring water to your fields, stop water leaving your fields or drain water out of any of your fields? | 73 | | no\_group\_count | How many plots are irrigated? | 74 | | yes\_group\_count | How many plots are not irrigated? | 75 | | no\_enough\_water | Are there months when you cannot get enough water for your crops? Indicate which months. | 76 | | months\_no\_water | Please select the months | 77 | | period\_use | For how long have you been using these methods of watering crops? (years) | 78 | | exper\_other | Do you have experience of such methods on other farms? | 79 | | other\_meth | Have you used other methods before? | 80 | | res\_change | Why did you change the way of watering your crops? | 81 | | memb\_assoc | Are you a member of an irrigation association? | 82 | | resp\_assoc | Do you have responsibilities in that association? | 83 | | fees\_water | Do you pay fees to use water? | 84 | | affect\_conflicts | Have you been affected by conflicts with other irrigators in the area? | 85 | | need\_money | If you started or changed the way you water your crops recently, did you need any money for it? | 86 | | money\_source | Where did the money came from? (list) | 87 | | money\_source\_other | Where did the money came from? (not on list) | 88 | | crops\_contr | Considering fields where you have applied water, how much do those crops contribute to your overall income? | 89 | | emply\_lab | In the most recent cultivation season, did you employ day labourers on fields? | 90 | | du\_labour | In the most recent cultivation season, did anyone in the household undertake day labour work on other farm? | 91 | | liv\_owned | What types of livestock do you own? (list) | 92 | | liv\_owned\_other | What types of livestock do you own? (not on list) | 93 | | liv\_count | Livestock count | 94 | | poultry | Own poultry? | 95 | | du\_look\_aftr\_cows | At the present time, does the household look after cows for someone else in return for milk or money? | 96 | | items\_owned | Which of the following items are owned by the household? (list) | 97 | | items\_owned\_other | Which of the following items are owned by the household? (not on list) | 98 | | no\_meals | How many meals do people in your household normally eat in a day? | 99 | | months\_lack\_food | Indicate which months, In the last 12 months have you faced a situation when you did not have enough food to feed the household? | 100 | | no\_food\_mitigation | When you have faced such a situation what do you do? | 101 | | gps\_Latitude | Location latitude (provided by smartphone) | 102 | | gps\_Longitude | Location longitude (provided by smartphone) | 103 | | gps\_Altitude | Location altitude (provided by smartphone) | 104 | | gps\_Accuracy | Location accuracy (provided by smartphone) | 105 | | instanceID | Unique identifier for the form data submission | 106 | 107 | 108 | -------------------------------------------------------------------------------- /learners/reference.md: -------------------------------------------------------------------------------- 1 | --- 2 | permalink: /reference/ 3 | --- 4 | 5 | ## Glossary 6 | 7 | FIXME This is a placeholder file. Please add content here. 8 | 9 | 10 | -------------------------------------------------------------------------------- /learners/setup.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: Setup 3 | --- 4 | 5 | ```{r include-setup-overview, child="files/setup-overview.md"} 6 | ``` 7 | 8 | ## Setup instructions for your workshop 9 | 10 | - If you are attending a workshop where Python will be taught, 11 | follow the [Python workshop setup instructions](setup-python-workshop.md). 12 | - If you are attentind a workshop where R will be taught, 13 | follow the [R workshop setup instructions](setup-r-workshop.md). 14 | 15 | 16 | -------------------------------------------------------------------------------- /profiles/learner-profiles.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: FIXME 3 | --- 4 | 5 | This is a placeholder file. Please add content here. 6 | -------------------------------------------------------------------------------- /renv/activate.R: -------------------------------------------------------------------------------- 1 | 2 | local({ 3 | 4 | # the requested version of renv 5 | version <- "1.1.4" 6 | attr(version, "sha") <- NULL 7 | 8 | # the project directory 9 | project <- Sys.getenv("RENV_PROJECT") 10 | if (!nzchar(project)) 11 | project <- getwd() 12 | 13 | # use start-up diagnostics if enabled 14 | diagnostics <- Sys.getenv("RENV_STARTUP_DIAGNOSTICS", unset = "FALSE") 15 | if (diagnostics) { 16 | start <- Sys.time() 17 | profile <- tempfile("renv-startup-", fileext = ".Rprof") 18 | utils::Rprof(profile) 19 | on.exit({ 20 | utils::Rprof(NULL) 21 | elapsed <- signif(difftime(Sys.time(), start, units = "auto"), digits = 2L) 22 | writeLines(sprintf("- renv took %s to run the autoloader.", format(elapsed))) 23 | writeLines(sprintf("- Profile: %s", profile)) 24 | print(utils::summaryRprof(profile)) 25 | }, add = TRUE) 26 | } 27 | 28 | # figure out whether the autoloader is enabled 29 | enabled <- local({ 30 | 31 | # first, check config option 32 | override <- getOption("renv.config.autoloader.enabled") 33 | if (!is.null(override)) 34 | return(override) 35 | 36 | # if we're being run in a context where R_LIBS is already set, 37 | # don't load -- presumably we're being run as a sub-process and 38 | # the parent process has already set up library paths for us 39 | rcmd <- Sys.getenv("R_CMD", unset = NA) 40 | rlibs <- Sys.getenv("R_LIBS", unset = NA) 41 | if (!is.na(rlibs) && !is.na(rcmd)) 42 | return(FALSE) 43 | 44 | # next, check environment variables 45 | # prefer using the configuration one in the future 46 | envvars <- c( 47 | "RENV_CONFIG_AUTOLOADER_ENABLED", 48 | "RENV_AUTOLOADER_ENABLED", 49 | "RENV_ACTIVATE_PROJECT" 50 | ) 51 | 52 | for (envvar in envvars) { 53 | envval <- Sys.getenv(envvar, unset = NA) 54 | if (!is.na(envval)) 55 | return(tolower(envval) %in% c("true", "t", "1")) 56 | } 57 | 58 | # enable by default 59 | TRUE 60 | 61 | }) 62 | 63 | # bail if we're not enabled 64 | if (!enabled) { 65 | 66 | # if we're not enabled, we might still need to manually load 67 | # the user profile here 68 | profile <- Sys.getenv("R_PROFILE_USER", unset = "~/.Rprofile") 69 | if (file.exists(profile)) { 70 | cfg <- Sys.getenv("RENV_CONFIG_USER_PROFILE", unset = "TRUE") 71 | if (tolower(cfg) %in% c("true", "t", "1")) 72 | sys.source(profile, envir = globalenv()) 73 | } 74 | 75 | return(FALSE) 76 | 77 | } 78 | 79 | # avoid recursion 80 | if (identical(getOption("renv.autoloader.running"), TRUE)) { 81 | warning("ignoring recursive attempt to run renv autoloader") 82 | return(invisible(TRUE)) 83 | } 84 | 85 | # signal that we're loading renv during R startup 86 | options(renv.autoloader.running = TRUE) 87 | on.exit(options(renv.autoloader.running = NULL), add = TRUE) 88 | 89 | # signal that we've consented to use renv 90 | options(renv.consent = TRUE) 91 | 92 | # load the 'utils' package eagerly -- this ensures that renv shims, which 93 | # mask 'utils' packages, will come first on the search path 94 | library(utils, lib.loc = .Library) 95 | 96 | # unload renv if it's already been loaded 97 | if ("renv" %in% loadedNamespaces()) 98 | unloadNamespace("renv") 99 | 100 | # load bootstrap tools 101 | ansify <- function(text) { 102 | if (renv_ansify_enabled()) 103 | renv_ansify_enhanced(text) 104 | else 105 | renv_ansify_default(text) 106 | } 107 | 108 | renv_ansify_enabled <- function() { 109 | 110 | override <- Sys.getenv("RENV_ANSIFY_ENABLED", unset = NA) 111 | if (!is.na(override)) 112 | return(as.logical(override)) 113 | 114 | pane <- Sys.getenv("RSTUDIO_CHILD_PROCESS_PANE", unset = NA) 115 | if (identical(pane, "build")) 116 | return(FALSE) 117 | 118 | testthat <- Sys.getenv("TESTTHAT", unset = "false") 119 | if (tolower(testthat) %in% "true") 120 | return(FALSE) 121 | 122 | iderun <- Sys.getenv("R_CLI_HAS_HYPERLINK_IDE_RUN", unset = "false") 123 | if (tolower(iderun) %in% "false") 124 | return(FALSE) 125 | 126 | TRUE 127 | 128 | } 129 | 130 | renv_ansify_default <- function(text) { 131 | text 132 | } 133 | 134 | renv_ansify_enhanced <- function(text) { 135 | 136 | # R help links 137 | pattern <- "`\\?(renv::(?:[^`])+)`" 138 | replacement <- "`\033]8;;x-r-help:\\1\a?\\1\033]8;;\a`" 139 | text <- gsub(pattern, replacement, text, perl = TRUE) 140 | 141 | # runnable code 142 | pattern <- "`(renv::(?:[^`])+)`" 143 | replacement <- "`\033]8;;x-r-run:\\1\a\\1\033]8;;\a`" 144 | text <- gsub(pattern, replacement, text, perl = TRUE) 145 | 146 | # return ansified text 147 | text 148 | 149 | } 150 | 151 | renv_ansify_init <- function() { 152 | 153 | envir <- renv_envir_self() 154 | if (renv_ansify_enabled()) 155 | assign("ansify", renv_ansify_enhanced, envir = envir) 156 | else 157 | assign("ansify", renv_ansify_default, envir = envir) 158 | 159 | } 160 | 161 | `%||%` <- function(x, y) { 162 | if (is.null(x)) y else x 163 | } 164 | 165 | catf <- function(fmt, ..., appendLF = TRUE) { 166 | 167 | quiet <- getOption("renv.bootstrap.quiet", default = FALSE) 168 | if (quiet) 169 | return(invisible()) 170 | 171 | msg <- sprintf(fmt, ...) 172 | cat(msg, file = stdout(), sep = if (appendLF) "\n" else "") 173 | 174 | invisible(msg) 175 | 176 | } 177 | 178 | header <- function(label, 179 | ..., 180 | prefix = "#", 181 | suffix = "-", 182 | n = min(getOption("width"), 78)) 183 | { 184 | label <- sprintf(label, ...) 185 | n <- max(n - nchar(label) - nchar(prefix) - 2L, 8L) 186 | if (n <= 0) 187 | return(paste(prefix, label)) 188 | 189 | tail <- paste(rep.int(suffix, n), collapse = "") 190 | paste0(prefix, " ", label, " ", tail) 191 | 192 | } 193 | 194 | heredoc <- function(text, leave = 0) { 195 | 196 | # remove leading, trailing whitespace 197 | trimmed <- gsub("^\\s*\\n|\\n\\s*$", "", text) 198 | 199 | # split into lines 200 | lines <- strsplit(trimmed, "\n", fixed = TRUE)[[1L]] 201 | 202 | # compute common indent 203 | indent <- regexpr("[^[:space:]]", lines) 204 | common <- min(setdiff(indent, -1L)) - leave 205 | text <- paste(substring(lines, common), collapse = "\n") 206 | 207 | # substitute in ANSI links for executable renv code 208 | ansify(text) 209 | 210 | } 211 | 212 | bootstrap <- function(version, library) { 213 | 214 | friendly <- renv_bootstrap_version_friendly(version) 215 | section <- header(sprintf("Bootstrapping renv %s", friendly)) 216 | catf(section) 217 | 218 | # attempt to download renv 219 | catf("- Downloading renv ... ", appendLF = FALSE) 220 | withCallingHandlers( 221 | tarball <- renv_bootstrap_download(version), 222 | error = function(err) { 223 | catf("FAILED") 224 | stop("failed to download:\n", conditionMessage(err)) 225 | } 226 | ) 227 | catf("OK") 228 | on.exit(unlink(tarball), add = TRUE) 229 | 230 | # now attempt to install 231 | catf("- Installing renv ... ", appendLF = FALSE) 232 | withCallingHandlers( 233 | status <- renv_bootstrap_install(version, tarball, library), 234 | error = function(err) { 235 | catf("FAILED") 236 | stop("failed to install:\n", conditionMessage(err)) 237 | } 238 | ) 239 | catf("OK") 240 | 241 | # add empty line to break up bootstrapping from normal output 242 | catf("") 243 | 244 | return(invisible()) 245 | } 246 | 247 | renv_bootstrap_tests_running <- function() { 248 | getOption("renv.tests.running", default = FALSE) 249 | } 250 | 251 | renv_bootstrap_repos <- function() { 252 | 253 | # get CRAN repository 254 | cran <- getOption("renv.repos.cran", "https://cloud.r-project.org") 255 | 256 | # check for repos override 257 | repos <- Sys.getenv("RENV_CONFIG_REPOS_OVERRIDE", unset = NA) 258 | if (!is.na(repos)) { 259 | 260 | # check for RSPM; if set, use a fallback repository for renv 261 | rspm <- Sys.getenv("RSPM", unset = NA) 262 | if (identical(rspm, repos)) 263 | repos <- c(RSPM = rspm, CRAN = cran) 264 | 265 | return(repos) 266 | 267 | } 268 | 269 | # check for lockfile repositories 270 | repos <- tryCatch(renv_bootstrap_repos_lockfile(), error = identity) 271 | if (!inherits(repos, "error") && length(repos)) 272 | return(repos) 273 | 274 | # retrieve current repos 275 | repos <- getOption("repos") 276 | 277 | # ensure @CRAN@ entries are resolved 278 | repos[repos == "@CRAN@"] <- cran 279 | 280 | # add in renv.bootstrap.repos if set 281 | default <- c(FALLBACK = "https://cloud.r-project.org") 282 | extra <- getOption("renv.bootstrap.repos", default = default) 283 | repos <- c(repos, extra) 284 | 285 | # remove duplicates that might've snuck in 286 | dupes <- duplicated(repos) | duplicated(names(repos)) 287 | repos[!dupes] 288 | 289 | } 290 | 291 | renv_bootstrap_repos_lockfile <- function() { 292 | 293 | lockpath <- Sys.getenv("RENV_PATHS_LOCKFILE", unset = "renv.lock") 294 | if (!file.exists(lockpath)) 295 | return(NULL) 296 | 297 | lockfile <- tryCatch(renv_json_read(lockpath), error = identity) 298 | if (inherits(lockfile, "error")) { 299 | warning(lockfile) 300 | return(NULL) 301 | } 302 | 303 | repos <- lockfile$R$Repositories 304 | if (length(repos) == 0) 305 | return(NULL) 306 | 307 | keys <- vapply(repos, `[[`, "Name", FUN.VALUE = character(1)) 308 | vals <- vapply(repos, `[[`, "URL", FUN.VALUE = character(1)) 309 | names(vals) <- keys 310 | 311 | return(vals) 312 | 313 | } 314 | 315 | renv_bootstrap_download <- function(version) { 316 | 317 | sha <- attr(version, "sha", exact = TRUE) 318 | 319 | methods <- if (!is.null(sha)) { 320 | 321 | # attempting to bootstrap a development version of renv 322 | c( 323 | function() renv_bootstrap_download_tarball(sha), 324 | function() renv_bootstrap_download_github(sha) 325 | ) 326 | 327 | } else { 328 | 329 | # attempting to bootstrap a release version of renv 330 | c( 331 | function() renv_bootstrap_download_tarball(version), 332 | function() renv_bootstrap_download_cran_latest(version), 333 | function() renv_bootstrap_download_cran_archive(version) 334 | ) 335 | 336 | } 337 | 338 | for (method in methods) { 339 | path <- tryCatch(method(), error = identity) 340 | if (is.character(path) && file.exists(path)) 341 | return(path) 342 | } 343 | 344 | stop("All download methods failed") 345 | 346 | } 347 | 348 | renv_bootstrap_download_impl <- function(url, destfile) { 349 | 350 | mode <- "wb" 351 | 352 | # https://bugs.r-project.org/bugzilla/show_bug.cgi?id=17715 353 | fixup <- 354 | Sys.info()[["sysname"]] == "Windows" && 355 | substring(url, 1L, 5L) == "file:" 356 | 357 | if (fixup) 358 | mode <- "w+b" 359 | 360 | args <- list( 361 | url = url, 362 | destfile = destfile, 363 | mode = mode, 364 | quiet = TRUE 365 | ) 366 | 367 | if ("headers" %in% names(formals(utils::download.file))) { 368 | headers <- renv_bootstrap_download_custom_headers(url) 369 | if (length(headers) && is.character(headers)) 370 | args$headers <- headers 371 | } 372 | 373 | do.call(utils::download.file, args) 374 | 375 | } 376 | 377 | renv_bootstrap_download_custom_headers <- function(url) { 378 | 379 | headers <- getOption("renv.download.headers") 380 | if (is.null(headers)) 381 | return(character()) 382 | 383 | if (!is.function(headers)) 384 | stopf("'renv.download.headers' is not a function") 385 | 386 | headers <- headers(url) 387 | if (length(headers) == 0L) 388 | return(character()) 389 | 390 | if (is.list(headers)) 391 | headers <- unlist(headers, recursive = FALSE, use.names = TRUE) 392 | 393 | ok <- 394 | is.character(headers) && 395 | is.character(names(headers)) && 396 | all(nzchar(names(headers))) 397 | 398 | if (!ok) 399 | stop("invocation of 'renv.download.headers' did not return a named character vector") 400 | 401 | headers 402 | 403 | } 404 | 405 | renv_bootstrap_download_cran_latest <- function(version) { 406 | 407 | spec <- renv_bootstrap_download_cran_latest_find(version) 408 | type <- spec$type 409 | repos <- spec$repos 410 | 411 | baseurl <- utils::contrib.url(repos = repos, type = type) 412 | ext <- if (identical(type, "source")) 413 | ".tar.gz" 414 | else if (Sys.info()[["sysname"]] == "Windows") 415 | ".zip" 416 | else 417 | ".tgz" 418 | name <- sprintf("renv_%s%s", version, ext) 419 | url <- paste(baseurl, name, sep = "/") 420 | 421 | destfile <- file.path(tempdir(), name) 422 | status <- tryCatch( 423 | renv_bootstrap_download_impl(url, destfile), 424 | condition = identity 425 | ) 426 | 427 | if (inherits(status, "condition")) 428 | return(FALSE) 429 | 430 | # report success and return 431 | destfile 432 | 433 | } 434 | 435 | renv_bootstrap_download_cran_latest_find <- function(version) { 436 | 437 | # check whether binaries are supported on this system 438 | binary <- 439 | getOption("renv.bootstrap.binary", default = TRUE) && 440 | !identical(.Platform$pkgType, "source") && 441 | !identical(getOption("pkgType"), "source") && 442 | Sys.info()[["sysname"]] %in% c("Darwin", "Windows") 443 | 444 | types <- c(if (binary) "binary", "source") 445 | 446 | # iterate over types + repositories 447 | for (type in types) { 448 | for (repos in renv_bootstrap_repos()) { 449 | 450 | # build arguments for utils::available.packages() call 451 | args <- list(type = type, repos = repos) 452 | 453 | # add custom headers if available -- note that 454 | # utils::available.packages() will pass this to download.file() 455 | if ("headers" %in% names(formals(utils::download.file))) { 456 | headers <- renv_bootstrap_download_custom_headers(repos) 457 | if (length(headers) && is.character(headers)) 458 | args$headers <- headers 459 | } 460 | 461 | # retrieve package database 462 | db <- tryCatch( 463 | as.data.frame( 464 | do.call(utils::available.packages, args), 465 | stringsAsFactors = FALSE 466 | ), 467 | error = identity 468 | ) 469 | 470 | if (inherits(db, "error")) 471 | next 472 | 473 | # check for compatible entry 474 | entry <- db[db$Package %in% "renv" & db$Version %in% version, ] 475 | if (nrow(entry) == 0) 476 | next 477 | 478 | # found it; return spec to caller 479 | spec <- list(entry = entry, type = type, repos = repos) 480 | return(spec) 481 | 482 | } 483 | } 484 | 485 | # if we got here, we failed to find renv 486 | fmt <- "renv %s is not available from your declared package repositories" 487 | stop(sprintf(fmt, version)) 488 | 489 | } 490 | 491 | renv_bootstrap_download_cran_archive <- function(version) { 492 | 493 | name <- sprintf("renv_%s.tar.gz", version) 494 | repos <- renv_bootstrap_repos() 495 | urls <- file.path(repos, "src/contrib/Archive/renv", name) 496 | destfile <- file.path(tempdir(), name) 497 | 498 | for (url in urls) { 499 | 500 | status <- tryCatch( 501 | renv_bootstrap_download_impl(url, destfile), 502 | condition = identity 503 | ) 504 | 505 | if (identical(status, 0L)) 506 | return(destfile) 507 | 508 | } 509 | 510 | return(FALSE) 511 | 512 | } 513 | 514 | renv_bootstrap_download_tarball <- function(version) { 515 | 516 | # if the user has provided the path to a tarball via 517 | # an environment variable, then use it 518 | tarball <- Sys.getenv("RENV_BOOTSTRAP_TARBALL", unset = NA) 519 | if (is.na(tarball)) 520 | return() 521 | 522 | # allow directories 523 | if (dir.exists(tarball)) { 524 | name <- sprintf("renv_%s.tar.gz", version) 525 | tarball <- file.path(tarball, name) 526 | } 527 | 528 | # bail if it doesn't exist 529 | if (!file.exists(tarball)) { 530 | 531 | # let the user know we weren't able to honour their request 532 | fmt <- "- RENV_BOOTSTRAP_TARBALL is set (%s) but does not exist." 533 | msg <- sprintf(fmt, tarball) 534 | warning(msg) 535 | 536 | # bail 537 | return() 538 | 539 | } 540 | 541 | catf("- Using local tarball '%s'.", tarball) 542 | tarball 543 | 544 | } 545 | 546 | renv_bootstrap_github_token <- function() { 547 | for (envvar in c("GITHUB_TOKEN", "GITHUB_PAT", "GH_TOKEN")) { 548 | envval <- Sys.getenv(envvar, unset = NA) 549 | if (!is.na(envval)) 550 | return(envval) 551 | } 552 | } 553 | 554 | renv_bootstrap_download_github <- function(version) { 555 | 556 | enabled <- Sys.getenv("RENV_BOOTSTRAP_FROM_GITHUB", unset = "TRUE") 557 | if (!identical(enabled, "TRUE")) 558 | return(FALSE) 559 | 560 | # prepare download options 561 | token <- renv_bootstrap_github_token() 562 | if (is.null(token)) 563 | token <- "" 564 | 565 | if (nzchar(Sys.which("curl")) && nzchar(token)) { 566 | fmt <- "--location --fail --header \"Authorization: token %s\"" 567 | extra <- sprintf(fmt, token) 568 | saved <- options("download.file.method", "download.file.extra") 569 | options(download.file.method = "curl", download.file.extra = extra) 570 | on.exit(do.call(base::options, saved), add = TRUE) 571 | } else if (nzchar(Sys.which("wget")) && nzchar(token)) { 572 | fmt <- "--header=\"Authorization: token %s\"" 573 | extra <- sprintf(fmt, token) 574 | saved <- options("download.file.method", "download.file.extra") 575 | options(download.file.method = "wget", download.file.extra = extra) 576 | on.exit(do.call(base::options, saved), add = TRUE) 577 | } 578 | 579 | url <- file.path("https://api.github.com/repos/rstudio/renv/tarball", version) 580 | name <- sprintf("renv_%s.tar.gz", version) 581 | destfile <- file.path(tempdir(), name) 582 | 583 | status <- tryCatch( 584 | renv_bootstrap_download_impl(url, destfile), 585 | condition = identity 586 | ) 587 | 588 | if (!identical(status, 0L)) 589 | return(FALSE) 590 | 591 | renv_bootstrap_download_augment(destfile) 592 | 593 | return(destfile) 594 | 595 | } 596 | 597 | # Add Sha to DESCRIPTION. This is stop gap until #890, after which we 598 | # can use renv::install() to fully capture metadata. 599 | renv_bootstrap_download_augment <- function(destfile) { 600 | sha <- renv_bootstrap_git_extract_sha1_tar(destfile) 601 | if (is.null(sha)) { 602 | return() 603 | } 604 | 605 | # Untar 606 | tempdir <- tempfile("renv-github-") 607 | on.exit(unlink(tempdir, recursive = TRUE), add = TRUE) 608 | untar(destfile, exdir = tempdir) 609 | pkgdir <- dir(tempdir, full.names = TRUE)[[1]] 610 | 611 | # Modify description 612 | desc_path <- file.path(pkgdir, "DESCRIPTION") 613 | desc_lines <- readLines(desc_path) 614 | remotes_fields <- c( 615 | "RemoteType: github", 616 | "RemoteHost: api.github.com", 617 | "RemoteRepo: renv", 618 | "RemoteUsername: rstudio", 619 | "RemotePkgRef: rstudio/renv", 620 | paste("RemoteRef: ", sha), 621 | paste("RemoteSha: ", sha) 622 | ) 623 | writeLines(c(desc_lines[desc_lines != ""], remotes_fields), con = desc_path) 624 | 625 | # Re-tar 626 | local({ 627 | old <- setwd(tempdir) 628 | on.exit(setwd(old), add = TRUE) 629 | 630 | tar(destfile, compression = "gzip") 631 | }) 632 | invisible() 633 | } 634 | 635 | # Extract the commit hash from a git archive. Git archives include the SHA1 636 | # hash as the comment field of the tarball pax extended header 637 | # (see https://www.kernel.org/pub/software/scm/git/docs/git-archive.html) 638 | # For GitHub archives this should be the first header after the default one 639 | # (512 byte) header. 640 | renv_bootstrap_git_extract_sha1_tar <- function(bundle) { 641 | 642 | # open the bundle for reading 643 | # We use gzcon for everything because (from ?gzcon) 644 | # > Reading from a connection which does not supply a 'gzip' magic 645 | # > header is equivalent to reading from the original connection 646 | conn <- gzcon(file(bundle, open = "rb", raw = TRUE)) 647 | on.exit(close(conn)) 648 | 649 | # The default pax header is 512 bytes long and the first pax extended header 650 | # with the comment should be 51 bytes long 651 | # `52 comment=` (11 chars) + 40 byte SHA1 hash 652 | len <- 0x200 + 0x33 653 | res <- rawToChar(readBin(conn, "raw", n = len)[0x201:len]) 654 | 655 | if (grepl("^52 comment=", res)) { 656 | sub("52 comment=", "", res) 657 | } else { 658 | NULL 659 | } 660 | } 661 | 662 | renv_bootstrap_install <- function(version, tarball, library) { 663 | 664 | # attempt to install it into project library 665 | dir.create(library, showWarnings = FALSE, recursive = TRUE) 666 | output <- renv_bootstrap_install_impl(library, tarball) 667 | 668 | # check for successful install 669 | status <- attr(output, "status") 670 | if (is.null(status) || identical(status, 0L)) 671 | return(status) 672 | 673 | # an error occurred; report it 674 | header <- "installation of renv failed" 675 | lines <- paste(rep.int("=", nchar(header)), collapse = "") 676 | text <- paste(c(header, lines, output), collapse = "\n") 677 | stop(text) 678 | 679 | } 680 | 681 | renv_bootstrap_install_impl <- function(library, tarball) { 682 | 683 | # invoke using system2 so we can capture and report output 684 | bin <- R.home("bin") 685 | exe <- if (Sys.info()[["sysname"]] == "Windows") "R.exe" else "R" 686 | R <- file.path(bin, exe) 687 | 688 | args <- c( 689 | "--vanilla", "CMD", "INSTALL", "--no-multiarch", 690 | "-l", shQuote(path.expand(library)), 691 | shQuote(path.expand(tarball)) 692 | ) 693 | 694 | system2(R, args, stdout = TRUE, stderr = TRUE) 695 | 696 | } 697 | 698 | renv_bootstrap_platform_prefix_default <- function() { 699 | 700 | # read version component 701 | version <- Sys.getenv("RENV_PATHS_VERSION", unset = "R-%v") 702 | 703 | # expand placeholders 704 | placeholders <- list( 705 | list("%v", format(getRversion()[1, 1:2])), 706 | list("%V", format(getRversion()[1, 1:3])) 707 | ) 708 | 709 | for (placeholder in placeholders) 710 | version <- gsub(placeholder[[1L]], placeholder[[2L]], version, fixed = TRUE) 711 | 712 | # include SVN revision for development versions of R 713 | # (to avoid sharing platform-specific artefacts with released versions of R) 714 | devel <- 715 | identical(R.version[["status"]], "Under development (unstable)") || 716 | identical(R.version[["nickname"]], "Unsuffered Consequences") 717 | 718 | if (devel) 719 | version <- paste(version, R.version[["svn rev"]], sep = "-r") 720 | 721 | version 722 | 723 | } 724 | 725 | renv_bootstrap_platform_prefix <- function() { 726 | 727 | # construct version prefix 728 | version <- renv_bootstrap_platform_prefix_default() 729 | 730 | # build list of path components 731 | components <- c(version, R.version$platform) 732 | 733 | # include prefix if provided by user 734 | prefix <- renv_bootstrap_platform_prefix_impl() 735 | if (!is.na(prefix) && nzchar(prefix)) 736 | components <- c(prefix, components) 737 | 738 | # build prefix 739 | paste(components, collapse = "/") 740 | 741 | } 742 | 743 | renv_bootstrap_platform_prefix_impl <- function() { 744 | 745 | # if an explicit prefix has been supplied, use it 746 | prefix <- Sys.getenv("RENV_PATHS_PREFIX", unset = NA) 747 | if (!is.na(prefix)) 748 | return(prefix) 749 | 750 | # if the user has requested an automatic prefix, generate it 751 | auto <- Sys.getenv("RENV_PATHS_PREFIX_AUTO", unset = NA) 752 | if (is.na(auto) && getRversion() >= "4.4.0") 753 | auto <- "TRUE" 754 | 755 | if (auto %in% c("TRUE", "True", "true", "1")) 756 | return(renv_bootstrap_platform_prefix_auto()) 757 | 758 | # empty string on failure 759 | "" 760 | 761 | } 762 | 763 | renv_bootstrap_platform_prefix_auto <- function() { 764 | 765 | prefix <- tryCatch(renv_bootstrap_platform_os(), error = identity) 766 | if (inherits(prefix, "error") || prefix %in% "unknown") { 767 | 768 | msg <- paste( 769 | "failed to infer current operating system", 770 | "please file a bug report at https://github.com/rstudio/renv/issues", 771 | sep = "; " 772 | ) 773 | 774 | warning(msg) 775 | 776 | } 777 | 778 | prefix 779 | 780 | } 781 | 782 | renv_bootstrap_platform_os <- function() { 783 | 784 | sysinfo <- Sys.info() 785 | sysname <- sysinfo[["sysname"]] 786 | 787 | # handle Windows + macOS up front 788 | if (sysname == "Windows") 789 | return("windows") 790 | else if (sysname == "Darwin") 791 | return("macos") 792 | 793 | # check for os-release files 794 | for (file in c("/etc/os-release", "/usr/lib/os-release")) 795 | if (file.exists(file)) 796 | return(renv_bootstrap_platform_os_via_os_release(file, sysinfo)) 797 | 798 | # check for redhat-release files 799 | if (file.exists("/etc/redhat-release")) 800 | return(renv_bootstrap_platform_os_via_redhat_release()) 801 | 802 | "unknown" 803 | 804 | } 805 | 806 | renv_bootstrap_platform_os_via_os_release <- function(file, sysinfo) { 807 | 808 | # read /etc/os-release 809 | release <- utils::read.table( 810 | file = file, 811 | sep = "=", 812 | quote = c("\"", "'"), 813 | col.names = c("Key", "Value"), 814 | comment.char = "#", 815 | stringsAsFactors = FALSE 816 | ) 817 | 818 | vars <- as.list(release$Value) 819 | names(vars) <- release$Key 820 | 821 | # get os name 822 | os <- tolower(sysinfo[["sysname"]]) 823 | 824 | # read id 825 | id <- "unknown" 826 | for (field in c("ID", "ID_LIKE")) { 827 | if (field %in% names(vars) && nzchar(vars[[field]])) { 828 | id <- vars[[field]] 829 | break 830 | } 831 | } 832 | 833 | # read version 834 | version <- "unknown" 835 | for (field in c("UBUNTU_CODENAME", "VERSION_CODENAME", "VERSION_ID", "BUILD_ID")) { 836 | if (field %in% names(vars) && nzchar(vars[[field]])) { 837 | version <- vars[[field]] 838 | break 839 | } 840 | } 841 | 842 | # join together 843 | paste(c(os, id, version), collapse = "-") 844 | 845 | } 846 | 847 | renv_bootstrap_platform_os_via_redhat_release <- function() { 848 | 849 | # read /etc/redhat-release 850 | contents <- readLines("/etc/redhat-release", warn = FALSE) 851 | 852 | # infer id 853 | id <- if (grepl("centos", contents, ignore.case = TRUE)) 854 | "centos" 855 | else if (grepl("redhat", contents, ignore.case = TRUE)) 856 | "redhat" 857 | else 858 | "unknown" 859 | 860 | # try to find a version component (very hacky) 861 | version <- "unknown" 862 | 863 | parts <- strsplit(contents, "[[:space:]]")[[1L]] 864 | for (part in parts) { 865 | 866 | nv <- tryCatch(numeric_version(part), error = identity) 867 | if (inherits(nv, "error")) 868 | next 869 | 870 | version <- nv[1, 1] 871 | break 872 | 873 | } 874 | 875 | paste(c("linux", id, version), collapse = "-") 876 | 877 | } 878 | 879 | renv_bootstrap_library_root_name <- function(project) { 880 | 881 | # use project name as-is if requested 882 | asis <- Sys.getenv("RENV_PATHS_LIBRARY_ROOT_ASIS", unset = "FALSE") 883 | if (asis) 884 | return(basename(project)) 885 | 886 | # otherwise, disambiguate based on project's path 887 | id <- substring(renv_bootstrap_hash_text(project), 1L, 8L) 888 | paste(basename(project), id, sep = "-") 889 | 890 | } 891 | 892 | renv_bootstrap_library_root <- function(project) { 893 | 894 | prefix <- renv_bootstrap_profile_prefix() 895 | 896 | path <- Sys.getenv("RENV_PATHS_LIBRARY", unset = NA) 897 | if (!is.na(path)) 898 | return(paste(c(path, prefix), collapse = "/")) 899 | 900 | path <- renv_bootstrap_library_root_impl(project) 901 | if (!is.null(path)) { 902 | name <- renv_bootstrap_library_root_name(project) 903 | return(paste(c(path, prefix, name), collapse = "/")) 904 | } 905 | 906 | renv_bootstrap_paths_renv("library", project = project) 907 | 908 | } 909 | 910 | renv_bootstrap_library_root_impl <- function(project) { 911 | 912 | root <- Sys.getenv("RENV_PATHS_LIBRARY_ROOT", unset = NA) 913 | if (!is.na(root)) 914 | return(root) 915 | 916 | type <- renv_bootstrap_project_type(project) 917 | if (identical(type, "package")) { 918 | userdir <- renv_bootstrap_user_dir() 919 | return(file.path(userdir, "library")) 920 | } 921 | 922 | } 923 | 924 | renv_bootstrap_validate_version <- function(version, description = NULL) { 925 | 926 | # resolve description file 927 | # 928 | # avoid passing lib.loc to `packageDescription()` below, since R will 929 | # use the loaded version of the package by default anyhow. note that 930 | # this function should only be called after 'renv' is loaded 931 | # https://github.com/rstudio/renv/issues/1625 932 | description <- description %||% packageDescription("renv") 933 | 934 | # check whether requested version 'version' matches loaded version of renv 935 | sha <- attr(version, "sha", exact = TRUE) 936 | valid <- if (!is.null(sha)) 937 | renv_bootstrap_validate_version_dev(sha, description) 938 | else 939 | renv_bootstrap_validate_version_release(version, description) 940 | 941 | if (valid) 942 | return(TRUE) 943 | 944 | # the loaded version of renv doesn't match the requested version; 945 | # give the user instructions on how to proceed 946 | dev <- identical(description[["RemoteType"]], "github") 947 | remote <- if (dev) 948 | paste("rstudio/renv", description[["RemoteSha"]], sep = "@") 949 | else 950 | paste("renv", description[["Version"]], sep = "@") 951 | 952 | # display both loaded version + sha if available 953 | friendly <- renv_bootstrap_version_friendly( 954 | version = description[["Version"]], 955 | sha = if (dev) description[["RemoteSha"]] 956 | ) 957 | 958 | fmt <- heredoc(" 959 | renv %1$s was loaded from project library, but this project is configured to use renv %2$s. 960 | - Use `renv::record(\"%3$s\")` to record renv %1$s in the lockfile. 961 | - Use `renv::restore(packages = \"renv\")` to install renv %2$s into the project library. 962 | ") 963 | catf(fmt, friendly, renv_bootstrap_version_friendly(version), remote) 964 | 965 | FALSE 966 | 967 | } 968 | 969 | renv_bootstrap_validate_version_dev <- function(version, description) { 970 | 971 | expected <- description[["RemoteSha"]] 972 | if (!is.character(expected)) 973 | return(FALSE) 974 | 975 | pattern <- sprintf("^\\Q%s\\E", version) 976 | grepl(pattern, expected, perl = TRUE) 977 | 978 | } 979 | 980 | renv_bootstrap_validate_version_release <- function(version, description) { 981 | expected <- description[["Version"]] 982 | is.character(expected) && identical(expected, version) 983 | } 984 | 985 | renv_bootstrap_hash_text <- function(text) { 986 | 987 | hashfile <- tempfile("renv-hash-") 988 | on.exit(unlink(hashfile), add = TRUE) 989 | 990 | writeLines(text, con = hashfile) 991 | tools::md5sum(hashfile) 992 | 993 | } 994 | 995 | renv_bootstrap_load <- function(project, libpath, version) { 996 | 997 | # try to load renv from the project library 998 | if (!requireNamespace("renv", lib.loc = libpath, quietly = TRUE)) 999 | return(FALSE) 1000 | 1001 | # warn if the version of renv loaded does not match 1002 | renv_bootstrap_validate_version(version) 1003 | 1004 | # execute renv load hooks, if any 1005 | hooks <- getHook("renv::autoload") 1006 | for (hook in hooks) 1007 | if (is.function(hook)) 1008 | tryCatch(hook(), error = warnify) 1009 | 1010 | # load the project 1011 | renv::load(project) 1012 | 1013 | TRUE 1014 | 1015 | } 1016 | 1017 | renv_bootstrap_profile_load <- function(project) { 1018 | 1019 | # if RENV_PROFILE is already set, just use that 1020 | profile <- Sys.getenv("RENV_PROFILE", unset = NA) 1021 | if (!is.na(profile) && nzchar(profile)) 1022 | return(profile) 1023 | 1024 | # check for a profile file (nothing to do if it doesn't exist) 1025 | path <- renv_bootstrap_paths_renv("profile", profile = FALSE, project = project) 1026 | if (!file.exists(path)) 1027 | return(NULL) 1028 | 1029 | # read the profile, and set it if it exists 1030 | contents <- readLines(path, warn = FALSE) 1031 | if (length(contents) == 0L) 1032 | return(NULL) 1033 | 1034 | # set RENV_PROFILE 1035 | profile <- contents[[1L]] 1036 | if (!profile %in% c("", "default")) 1037 | Sys.setenv(RENV_PROFILE = profile) 1038 | 1039 | profile 1040 | 1041 | } 1042 | 1043 | renv_bootstrap_profile_prefix <- function() { 1044 | profile <- renv_bootstrap_profile_get() 1045 | if (!is.null(profile)) 1046 | return(file.path("profiles", profile, "renv")) 1047 | } 1048 | 1049 | renv_bootstrap_profile_get <- function() { 1050 | profile <- Sys.getenv("RENV_PROFILE", unset = "") 1051 | renv_bootstrap_profile_normalize(profile) 1052 | } 1053 | 1054 | renv_bootstrap_profile_set <- function(profile) { 1055 | profile <- renv_bootstrap_profile_normalize(profile) 1056 | if (is.null(profile)) 1057 | Sys.unsetenv("RENV_PROFILE") 1058 | else 1059 | Sys.setenv(RENV_PROFILE = profile) 1060 | } 1061 | 1062 | renv_bootstrap_profile_normalize <- function(profile) { 1063 | 1064 | if (is.null(profile) || profile %in% c("", "default")) 1065 | return(NULL) 1066 | 1067 | profile 1068 | 1069 | } 1070 | 1071 | renv_bootstrap_path_absolute <- function(path) { 1072 | 1073 | substr(path, 1L, 1L) %in% c("~", "/", "\\") || ( 1074 | substr(path, 1L, 1L) %in% c(letters, LETTERS) && 1075 | substr(path, 2L, 3L) %in% c(":/", ":\\") 1076 | ) 1077 | 1078 | } 1079 | 1080 | renv_bootstrap_paths_renv <- function(..., profile = TRUE, project = NULL) { 1081 | renv <- Sys.getenv("RENV_PATHS_RENV", unset = "renv") 1082 | root <- if (renv_bootstrap_path_absolute(renv)) NULL else project 1083 | prefix <- if (profile) renv_bootstrap_profile_prefix() 1084 | components <- c(root, renv, prefix, ...) 1085 | paste(components, collapse = "/") 1086 | } 1087 | 1088 | renv_bootstrap_project_type <- function(path) { 1089 | 1090 | descpath <- file.path(path, "DESCRIPTION") 1091 | if (!file.exists(descpath)) 1092 | return("unknown") 1093 | 1094 | desc <- tryCatch( 1095 | read.dcf(descpath, all = TRUE), 1096 | error = identity 1097 | ) 1098 | 1099 | if (inherits(desc, "error")) 1100 | return("unknown") 1101 | 1102 | type <- desc$Type 1103 | if (!is.null(type)) 1104 | return(tolower(type)) 1105 | 1106 | package <- desc$Package 1107 | if (!is.null(package)) 1108 | return("package") 1109 | 1110 | "unknown" 1111 | 1112 | } 1113 | 1114 | renv_bootstrap_user_dir <- function() { 1115 | dir <- renv_bootstrap_user_dir_impl() 1116 | path.expand(chartr("\\", "/", dir)) 1117 | } 1118 | 1119 | renv_bootstrap_user_dir_impl <- function() { 1120 | 1121 | # use local override if set 1122 | override <- getOption("renv.userdir.override") 1123 | if (!is.null(override)) 1124 | return(override) 1125 | 1126 | # use R_user_dir if available 1127 | tools <- asNamespace("tools") 1128 | if (is.function(tools$R_user_dir)) 1129 | return(tools$R_user_dir("renv", "cache")) 1130 | 1131 | # try using our own backfill for older versions of R 1132 | envvars <- c("R_USER_CACHE_DIR", "XDG_CACHE_HOME") 1133 | for (envvar in envvars) { 1134 | root <- Sys.getenv(envvar, unset = NA) 1135 | if (!is.na(root)) 1136 | return(file.path(root, "R/renv")) 1137 | } 1138 | 1139 | # use platform-specific default fallbacks 1140 | if (Sys.info()[["sysname"]] == "Windows") 1141 | file.path(Sys.getenv("LOCALAPPDATA"), "R/cache/R/renv") 1142 | else if (Sys.info()[["sysname"]] == "Darwin") 1143 | "~/Library/Caches/org.R-project.R/R/renv" 1144 | else 1145 | "~/.cache/R/renv" 1146 | 1147 | } 1148 | 1149 | renv_bootstrap_version_friendly <- function(version, shafmt = NULL, sha = NULL) { 1150 | sha <- sha %||% attr(version, "sha", exact = TRUE) 1151 | parts <- c(version, sprintf(shafmt %||% " [sha: %s]", substring(sha, 1L, 7L))) 1152 | paste(parts, collapse = "") 1153 | } 1154 | 1155 | renv_bootstrap_exec <- function(project, libpath, version) { 1156 | if (!renv_bootstrap_load(project, libpath, version)) 1157 | renv_bootstrap_run(project, libpath, version) 1158 | } 1159 | 1160 | renv_bootstrap_run <- function(project, libpath, version) { 1161 | 1162 | # perform bootstrap 1163 | bootstrap(version, libpath) 1164 | 1165 | # exit early if we're just testing bootstrap 1166 | if (!is.na(Sys.getenv("RENV_BOOTSTRAP_INSTALL_ONLY", unset = NA))) 1167 | return(TRUE) 1168 | 1169 | # try again to load 1170 | if (requireNamespace("renv", lib.loc = libpath, quietly = TRUE)) { 1171 | return(renv::load(project = project)) 1172 | } 1173 | 1174 | # failed to download or load renv; warn the user 1175 | msg <- c( 1176 | "Failed to find an renv installation: the project will not be loaded.", 1177 | "Use `renv::activate()` to re-initialize the project." 1178 | ) 1179 | 1180 | warning(paste(msg, collapse = "\n"), call. = FALSE) 1181 | 1182 | } 1183 | 1184 | renv_json_read <- function(file = NULL, text = NULL) { 1185 | 1186 | jlerr <- NULL 1187 | 1188 | # if jsonlite is loaded, use that instead 1189 | if ("jsonlite" %in% loadedNamespaces()) { 1190 | 1191 | json <- tryCatch(renv_json_read_jsonlite(file, text), error = identity) 1192 | if (!inherits(json, "error")) 1193 | return(json) 1194 | 1195 | jlerr <- json 1196 | 1197 | } 1198 | 1199 | # otherwise, fall back to the default JSON reader 1200 | json <- tryCatch(renv_json_read_default(file, text), error = identity) 1201 | if (!inherits(json, "error")) 1202 | return(json) 1203 | 1204 | # report an error 1205 | if (!is.null(jlerr)) 1206 | stop(jlerr) 1207 | else 1208 | stop(json) 1209 | 1210 | } 1211 | 1212 | renv_json_read_jsonlite <- function(file = NULL, text = NULL) { 1213 | text <- paste(text %||% readLines(file, warn = FALSE), collapse = "\n") 1214 | jsonlite::fromJSON(txt = text, simplifyVector = FALSE) 1215 | } 1216 | 1217 | renv_json_read_patterns <- function() { 1218 | 1219 | list( 1220 | 1221 | # objects 1222 | list("{", "\t\n\tobject(\t\n\t", TRUE), 1223 | list("}", "\t\n\t)\t\n\t", TRUE), 1224 | 1225 | # arrays 1226 | list("[", "\t\n\tarray(\t\n\t", TRUE), 1227 | list("]", "\n\t\n)\n\t\n", TRUE), 1228 | 1229 | # maps 1230 | list(":", "\t\n\t=\t\n\t", TRUE), 1231 | 1232 | # newlines 1233 | list("\\u000a", "\n", FALSE) 1234 | 1235 | ) 1236 | 1237 | } 1238 | 1239 | renv_json_read_envir <- function() { 1240 | 1241 | envir <- new.env(parent = emptyenv()) 1242 | 1243 | envir[["+"]] <- `+` 1244 | envir[["-"]] <- `-` 1245 | 1246 | envir[["object"]] <- function(...) { 1247 | result <- list(...) 1248 | names(result) <- as.character(names(result)) 1249 | result 1250 | } 1251 | 1252 | envir[["array"]] <- list 1253 | 1254 | envir[["true"]] <- TRUE 1255 | envir[["false"]] <- FALSE 1256 | envir[["null"]] <- NULL 1257 | 1258 | envir 1259 | 1260 | } 1261 | 1262 | renv_json_read_remap <- function(object, patterns) { 1263 | 1264 | # repair names if necessary 1265 | if (!is.null(names(object))) { 1266 | 1267 | nms <- names(object) 1268 | for (pattern in patterns) 1269 | nms <- gsub(pattern[[2L]], pattern[[1L]], nms, fixed = TRUE) 1270 | names(object) <- nms 1271 | 1272 | } 1273 | 1274 | # repair strings if necessary 1275 | if (is.character(object)) { 1276 | for (pattern in patterns) 1277 | object <- gsub(pattern[[2L]], pattern[[1L]], object, fixed = TRUE) 1278 | } 1279 | 1280 | # recurse for other objects 1281 | if (is.recursive(object)) 1282 | for (i in seq_along(object)) 1283 | object[i] <- list(renv_json_read_remap(object[[i]], patterns)) 1284 | 1285 | # return remapped object 1286 | object 1287 | 1288 | } 1289 | 1290 | renv_json_read_default <- function(file = NULL, text = NULL) { 1291 | 1292 | # read json text 1293 | text <- paste(text %||% readLines(file, warn = FALSE), collapse = "\n") 1294 | 1295 | # convert into something the R parser will understand 1296 | patterns <- renv_json_read_patterns() 1297 | transformed <- text 1298 | for (pattern in patterns) 1299 | transformed <- gsub(pattern[[1L]], pattern[[2L]], transformed, fixed = TRUE) 1300 | 1301 | # parse it 1302 | rfile <- tempfile("renv-json-", fileext = ".R") 1303 | on.exit(unlink(rfile), add = TRUE) 1304 | writeLines(transformed, con = rfile) 1305 | json <- parse(rfile, keep.source = FALSE, srcfile = NULL)[[1L]] 1306 | 1307 | # evaluate in safe environment 1308 | result <- eval(json, envir = renv_json_read_envir()) 1309 | 1310 | # fix up strings if necessary -- do so only with reversible patterns 1311 | patterns <- Filter(function(pattern) pattern[[3L]], patterns) 1312 | renv_json_read_remap(result, patterns) 1313 | 1314 | } 1315 | 1316 | 1317 | # load the renv profile, if any 1318 | renv_bootstrap_profile_load(project) 1319 | 1320 | # construct path to library root 1321 | root <- renv_bootstrap_library_root(project) 1322 | 1323 | # construct library prefix for platform 1324 | prefix <- renv_bootstrap_platform_prefix() 1325 | 1326 | # construct full libpath 1327 | libpath <- file.path(root, prefix) 1328 | 1329 | # run bootstrap code 1330 | renv_bootstrap_exec(project, libpath, version) 1331 | 1332 | invisible() 1333 | 1334 | }) 1335 | -------------------------------------------------------------------------------- /renv/profile: -------------------------------------------------------------------------------- 1 | lesson-requirements 2 | -------------------------------------------------------------------------------- /renv/profiles/lesson-requirements/renv/.gitignore: -------------------------------------------------------------------------------- 1 | library/ 2 | local/ 3 | cellar/ 4 | lock/ 5 | python/ 6 | sandbox/ 7 | staging/ 8 | -------------------------------------------------------------------------------- /renv/profiles/lesson-requirements/renv/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "bioconductor.version": null, 3 | "external.libraries": [], 4 | "ignored.packages": [], 5 | "package.dependency.fields": [ 6 | "Imports", 7 | "Depends", 8 | "LinkingTo" 9 | ], 10 | "ppm.enabled": null, 11 | "ppm.ignored.urls": [], 12 | "r.version": null, 13 | "snapshot.type": "implicit", 14 | "use.cache": true, 15 | "vcs.ignore.cellar": true, 16 | "vcs.ignore.library": true, 17 | "vcs.ignore.local": true, 18 | "vcs.manage.ignores": true 19 | } 20 | -------------------------------------------------------------------------------- /setup-python-workshop.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: Setup for Python workshop 4 | --- 5 | 6 | ```{r include-setup-overview, child="files/setup-overview.md"} 7 | ``` 8 | 9 | ```{r include-setup-data, child="files/setup-data.md"} 10 | ``` 11 | 12 | ## Software 13 | 14 | | Software | Install | Manual | Available for | Description | 15 | | --------------------- | ------------------------------- | ------ | --------------------- | ------------------------------------------------ | 16 | | Spreadsheet program | [Download LibreOffice](https://www.libreoffice.org/download/download/) | [LibreOffice documentation](https://documentation.libreoffice.org/en/english-documentation/) | Linux, MacOS, Windows | Spreadsheet program for organizing tabular data. | 17 | | OpenRefine | [Download OpenRefine](https://openrefine.org/download.html) | [OpenRefine documentation](https://openrefine.org/docs) | Linux, MacOS, Windows | | 18 | | Python | See install instructions below. | | Linux, MacOS, Windows | | 19 | | DB Browser for SQLite | [Download DB Browser for SQLite](https://sqlitebrowser.org/dl/) | | Linux, MacOS, Windows | | 20 | 21 | ```{r include-setup-spreadsheet, child="files/setup-spreadsheet.md"} 22 | ``` 23 | 24 | ```{r include-setup-openrefine, child="files/setup-openrefine.md"} 25 | ``` 26 | 27 | ```{r include-setup-python, child="files/setup-python.md"} 28 | ``` 29 | 30 | ```{r include-setup-sql, child="files/setup-sql.md"} 31 | ``` 32 | 33 | Congratulations! You are now ready for the workshop! 34 | 35 | 36 | -------------------------------------------------------------------------------- /setup-r-workshop.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: Setup for R workshop 4 | --- 5 | 6 | ```{r include-setup-overview, child="files/setup-overview.md"} 7 | ``` 8 | 9 | ```{r include-setup-data, child="files/setup-data.md"} 10 | ``` 11 | 12 | ## Software 13 | 14 | | Software | Install | Manual | Available for | Description | 15 | | --------------------- | ------------------------------- | --------------------- | --------------------- | ------------------------------------------------ | 16 | | Spreadsheet program | [Download LibreOffice](https://www.libreoffice.org/download/download-libreoffice/) | [LibreOffice documentation](https://documentation.libreoffice.org/en/english-documentation/) | Linux, MacOS, Windows | Spreadsheet program for organizing tabular data. | 17 | | OpenRefine | [Download OpenRefine](https://openrefine.org/download.html) | [OpenRefine documentation](https://openrefine.org/docs) | Linux, MacOS, Windows | | 18 | | R | See install instructions below. | | Linux, MacOS, Windows | | 19 | | RStudio | [Download RStudio](https://posit.co/download/rstudio-desktop/#download) | [RStudio Cheatsheet](https://raw.githubusercontent.com/rstudio/cheatsheets/main/rstudio-ide.pdf) | Linux, MacOS, Windows | | 20 | | DB Browser for SQLite | [Download DB Browser for SQLite](https://sqlitebrowser.org/dl/) | Linux, MacOS, Windows | | | 21 | 22 | ```{r include-setup-spreadsheet, child="files/setup-spreadsheet.md"} 23 | ``` 24 | 25 | ```{r include-setup-openrefine, child="files/setup-openrefine.md"} 26 | ``` 27 | 28 | ```{r include-setup-r, child="files/setup-r.md"} 29 | ``` 30 | 31 | ```{r include-setup-sql, child="files/setup-sql.md"} 32 | ``` 33 | 34 | Congratulations! You are now ready for the workshop! 35 | 36 | 37 | -------------------------------------------------------------------------------- /site/README.md: -------------------------------------------------------------------------------- 1 | This directory contains rendered lesson materials. Please do not edit files 2 | here. 3 | --------------------------------------------------------------------------------