{"id":18664756,"url":"https://github.com/reilly-conceptscognitionlab/conversationalign","last_synced_at":"2025-04-11T22:30:41.281Z","repository":{"id":181222381,"uuid":"664809897","full_name":"Reilly-ConceptsCognitionLab/ConversationAlign","owner":"Reilly-ConceptsCognitionLab","description":"An R package for analyzing semantic and affective alignment between conversation partners in natural language transcripts","archived":false,"fork":false,"pushed_at":"2025-03-04T21:41:17.000Z","size":78379,"stargazers_count":10,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-25T19:21:26.973Z","etag":null,"topics":["communication","conversation","dyadic-data","language","natural-language-processing","psycholinguistics"],"latest_commit_sha":null,"homepage":"https://reilly-conceptscognitionlab.github.io/ConversationAlign/","language":"R","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Reilly-ConceptsCognitionLab.png","metadata":{"files":{"readme":"README.Rmd","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-07-10T19:53:33.000Z","updated_at":"2025-03-04T21:31:20.000Z","dependencies_parsed_at":"2023-10-16T08:48:36.316Z","dependency_job_id":"b750c08c-01c4-43d4-b28f-d1249c88429e","html_url":"https://github.com/Reilly-ConceptsCognitionLab/ConversationAlign","commit_stats":null,"previous_names":["reilly-conceptscognitionlab/conversationalign"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Reilly-ConceptsCognitionLab%2FConversationAlign","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Reilly-ConceptsCognitionLab%2FConversationAlign/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Reilly-ConceptsCognitionLab%2FConversationAlign/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Reilly-ConceptsCognitionLab%2FConversationAlign/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Reilly-ConceptsCognitionLab","download_url":"https://codeload.github.com/Reilly-ConceptsCognitionLab/ConversationAlign/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248489466,"owners_count":21112579,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["communication","conversation","dyadic-data","language","natural-language-processing","psycholinguistics"],"created_at":"2024-11-07T08:24:51.140Z","updated_at":"2025-04-11T22:30:41.265Z","avatar_url":"https://github.com/Reilly-ConceptsCognitionLab.png","language":"R","funding_links":[],"categories":[],"sub_categories":[],"readme":"---\noutput: github_document\n---\n\u003c!-- README.md is generated from README.Rmd. Please edit that file --\u003e\n\n```{r, include = FALSE}\nknitr::opts_chunk$set(\n  collapse = TRUE,\n  comment = \"#\u003e\",\n  fig.path = \"man/figures/\",\n  out.width = \"100%\",\n  fig.align='left'\n)\n```\n\n# ConversationAlign\n\u003c!-- badges: start --\u003e\n  [![R-CMD-check](https://github.com/reilly-lab/ConversationAlign/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/reilly-lab/ConversationAlign/actions/workflows/R-CMD-check.yaml)\n  \u003c!-- badges: end --\u003e\n\n\u003c!-- ```{r, echo=F, out.width='70%', out.height='60%', out.extra='style=\"float:right; padding:5px\"'} --\u003e\n\u003c!--  knitr::include_graphics(\"man/figures/convo.jpeg\") --\u003e\n\u003c!-- ``` --\u003e\nConversationAlign analyzes alignment between interlocutors (conversation partners) engaged in two-person conversations.  ConversationAlign works on language transcripts. It can handle text files (.txt) or comma separated value (.csv) spreadsheet style files. ConversationAlign transforms raw language data into simultaneous time series objects spanning 30 possible dimensions via an embedded lookup database. \n\u003cbr/\u003e\n\n# Overview\nHere's a schematic of the guts of the program... \n\n![overview of ConversationAlign](man/figures/overview.png){width=300px, height=600px} \n\n# Before starting: Prep your data\nConversationAlign can handle a home brew of your own preferred format. However, your transcripts must have the following header columns at a bare minimum: \u003cbr/\u003e\n1) Participant identifier (named Interlocutor', 'Speaker', or 'Participant') \u003cbr/\u003e\n2) Text (named 'Text', 'Utterance', or 'Turn') \u003cbr/\u003e\n\nThe order of your columns does not matter. Any other data in your transcripts (e.g., metadata, timestamps, grouping variables) will be retained. Here's an example of a transcript that will work. Don't worry about stripping punctuation. We will do that for you. \u003cbr/\u003e\n  \n![Example transcript from Taylor Swift-Ellen DeGeneres Interview, 2013](man/figures/example1_ts_edg.jpeg){width=800px, height=200px} \u003cbr/\u003e\n  \nConsiderations in prepping your language transcripts for ConversationAlign: \u003cbr/\u003e\n\n1) Save each conversation transcript as a separate file (e.g., MaryJoe_FirstDateTalk.txt) \n2) Be careful/deliberate about your filenaming convention. The filename for each conversation will become its event ID in the dataframe\n3) Move all your language transcripts to be analyzed into one folder (e.g., \"my_transcripts\") in the same directory you are running your R script. \n5) If you have metadata (e.g., age, timestamps, grouping variables), you can either append this to your original transcript or merge the metdata as a separate file. This is a useful option when you have many individual difference and demographic details.\n\n# Installation\nInstall the development version of ConversationAlign from [GitHub](https://github.com/) by entering the following in your console or script:\n\n``` {r, eval=F}\ninstall.packages(\"devtools\")\ndevtools::install_github(\"Reilly-ConceptsCognitionLab/ConversationAlign\")\n```\n\n```{r, include=FALSE}\n# load package wihtout printing anything\nlibrary(ConversationAlign)\n```\n\n# Read your transcripts into R\n## read_dyads()\nThis function will read all your files and concatenate them into a single dataframe, appending document IDs.  You can call this dataframe whatever you like. 'read_dyads' will default to reading all csv and txt files in a folder called my_transcripts. Just remember that when you are finished processing a set of transcripts, make sure to move them out of that folder. You can think of 'my_transcripts' as a staging area for loading data into ConversationAlign. \u003cbr/\u003e\n\n```{r, eval=F}\nMyRawLangSamples \u003c- read_dyads()\n#if you want to specify a different folder, supply your own path\nMyRawLangSamples \u003c- read_dyads(\"/my_custompath\")\n```\n\n```{r, echo=FALSE}\n# code to show the read data, which is supplied manually (file not included)\n# this is real data manually defined as to not include extra data in the package and make it take up more memory\n\n# manually define 16 rows of the proper data\nexampleRead \u003c- data.frame(Event_ID = \"taylorellen\",\n                          Participant_ID = rep(c(\"Taylor\", \"Ellen\"), 8),\n                          RawText = c(\"That was an amazing montage.\",\n                                      \"I know. And that's that's no no one's in there. We're not gonna do it to you today.\",\n                                      \"It's not amateur hour. No,\",\n                                      \"no, I'm not going to your because I can't talk how I did it the first time you were the best scare. Well, I don't know. Sarah Paulson was pretty good, too. But\",\n                                      \"that was a near death experience\",\n                                      \"it kind of was you went down\",\n                                      \"Yeah.\",\n                                      \"Were there injuries?\",\n                                      \"There were several ways I could have died.\",\n                                      \"Well,now you're being dramatic.\", \n                                      \"Yeah,\",\n                                      \"yeah. No, that's extreme.\",\n                                      \"Yeah.\",\n                                      \"It- I really just was watching that backstage. And I was just thinking like, thank you so much for going so above and beyond to make people happy. Yeah,\",\n                                      \"well,\",\n                                      \"that's not a good example of it\"))\n\nknitr::kable(exampleRead)\n```\n\u003c!-- \u003cbr/\u003e --\u003e\n\u003c!-- ![Example of read transcripts from Taylor Swift-Ellen DeGeneres Interview, 2013](man/figures/example2_ts_edg.jpeg){width=400px, height=600px} \u003cbr/\u003e --\u003e\n\n# Clean your transcripts\n## clean_dyads()\n'clean_dyads' uses numerous regex to clean and format the data your just read into R in the previous step. Although there are many cleaning steps, here are the big ones:\n1) to lowercase\n2) omit stopwords\n3) replace contractions (e.g., 'you're' to 'you are')\n4) tick marks to apostrophes\n5) hypens to spaces\n6) omits numerals\n7) omits/squishes extraneous white space\n8) lemmatization \u003cbr/\u003e\n\nConversationAlign calls the textstem package as a dependency to lemmatize your language transcript. This converts morphologiocal derivatives to their root forms. The default is lemmatize=T. Sometimes you want to retain language output in its native form. If this is the case, change the argument in clean_dyads to lemmatize=F. \u003cbr/\u003e\n\n'clean_dyads' outputs word count metrics pre/post cleaning by dyad and interlocutor. This can be useful if you are interested in whether one person just doesn't produce many words or produces a great deal of empty utterances.\u003cbr/\u003e\n```{r, eval=F}\nMyCleanLangSamples \u003c- clean_dyads(MyRawLangSamples) #default is lemmatize=TRUE\n#If you do NOT want your language sample lemmatized, change the lemmatize argument to F or FALSE\nMyCleanLangSamples \u003c- clean_dyads(MyRawLangSamples, lemmatize=FALSE)\n```\n\n```{r, echo=FALSE}\nexampleClean \u003c- clean_dyads(exampleRead, lemmatize = FALSE)\nknitr::kable(exampleClean[1:15, ])\n```\n\n\u003c!-- ![Example of cleaned transcripts from Taylor Swift-Ellen DeGeneres Interview, 2013](man/figures/example3_ts_edg.jpeg){width=300px, height=400px} \u003cbr/\u003e --\u003e\n\n# Align your transcripts\n## align_dyads()\nThis is where a lot of the magic happens. align_dyads will take the cleaned dataframe you created in the last step and yoke values to every word by indexing a lookup database. The \"align\" step yokes data to each word in the cleaned transcript text then structures a dataframe by speaker (\"Participant_ID\"), exchange (\"exchangecount\"), and turn (\"turncount\") across each dyad (\"event_id\"). \u003cbr/\u003e\n\nYou will be prompted to select one of more variables (and up to three) to yoke data to that will be used in later steps to compute alignment indices. You will be shown a menu wherein you can select up to three variables to be yoked to your text. Following the menu steps, enter the number of each variable you would like with a space separating values (e.g., \"10 14 19\"). \u003cbr/\u003e\n\nHere are your choices: \u003cbr/\u003e\n\nanger, anxiety, boredom, closeness, confusion, dominance, doubt, empathy, encouragement, excitement, guilt, happiness, hope, hostility, politeness, sadness, stress, surprise, trust, valence, age of acquisition, word length (by letters), morphemes per turn, prevalence (how many people know this word), number of word senses (polysemy), word frequency (lg10), arousal, concreteness, semantic diversity, and semantic neighbors. \u003cbr/\u003e\n\nVariable key here: \u003cbr/\u003e\nhttps://reilly-lab.github.io/ConversationAlign_VariableLookupKey.pdf \u003cbr/\u003e\n\u003cbr/\u003e\n\nConversationAlign will prompt you to append any metadata you would like to add. This joins information from a separate file (e.g., neuropsych scores, ages, etc). Just give ConversationAlign a filepath to your CSV data or click \"Enter\" to skip this step. A metadata file might look like this:\n\nMETADATA IMAGE HERE \u003cbr/\u003e\n\nRun align_dyads on the cleaned dyads object you created using the clean_dyads function.\u003cbr/\u003e\n\n```{r, eval=F}\nMyAlignedDyads \u003c- align_dyads(MyCleanLangSamples)\n```\n\n![Example aligned transcripts anger, anxiety, boredom from Taylor Swift-Ellen DeGeneres Interview, 2013](man/figures/example4_ts_edg.jpeg){width=800px, height=200px} \u003cbr/\u003e\n\n\n# Summarize transcripts\nThis last step consists of three methods, each of which computes a seperate index of alignment.\n\n## summarize_dyads_auc()\nThis returns the difference time series AUC (dAUC) for every variable of interest you specified. For example, summarize_dyads_auc will append dAUC values for hostility (if that's what you're interested in). \u003cbr/\u003e\n\n## summarize_dyads_covar()\nThis returns a spearman correlation coefficient and range of lagged Pearson correlation coefficients for each variable of interest. A vector of Lags/leads for Pearson correlations are supplied as a parameter.\n\u003cbr/\u003e\n\n## summarize_dyads_slope()\nThis return the intercept and slope of a simple linear regression for each interlocutor and the difference time series over each variable of interest. This provides a measure of change over time, providing information on who aligns to whom.\n\u003cbr/\u003e\n\u003c!-- Link here to read more about what dAUC, Spearman, and slope mean in the context of alignment (or look at the figure above for an illustration): LINK TO METHOD --\u003e\n\n```{r, eval=F}\nMyFinalDataframe_AUC \u003c- summarize_dyads_auc(MyAlignedDyads, resample = T) #resample=T computes AUC by homogenizing the length of all dyads to the shortest tramscript (number of turns) \n\nMyFinalDataframe_Covar \u003c- summarize_dyads_covar(MyAlignedDyads, lags = c(-2, -1, 1, 2)) # lags are supplied as a vector, defaulting to a range of [-3, 3]\n\nMyFinalDataframe_Slope \u003c- summarize_dyads_slope(MyAlignedDyads, resample = F) # for auc and slope, when resample=F, it becomes much more difficult to compare metrics between conversations of different lengths.\n```\n\n# Caveat emptor\n## Things you must be careful about\nAny analysis of language comes with assumptions and potential bias. For example, there are some instances where a researcher might care about morphemes and grammatical elements such as 'the', 'a', 'and', etc..  The default for ConversationAlign is to omit these as stopwords and to average across all open class words (e.g., nouns, verbs) in each turn by interlocutor. There are some specific cases where this can all go wrong. Here's what you need to consider: \u003cbr/\u003e\n\n1. \u003cspan style=\"color:red;\"\u003eStopwords \u003c/span\u003e: The package omits stopwords. [See the stopword list here]( https://osf.io/atf5q/) if you would like to inspect this list. We included greetings, idioms, filler words, numerals, and pronouns in the omissions list. \u003cbr/\u003e\n\n2. \u003cspan style=\"color:red;\"\u003eLemmatization \u003c/span\u003e: The package will lemmatize your language transcripts by default. Lemmatization transforms inflected forms (e.g., standing, stands) into their root or dictionary entry (e.g., stand). This helps for yoking offline values (e.g., happiness, concreteness) to each word and also entails what NLP folks refer to as 'term aggregation'. However, sometimes you might NOT want to lemmatize. You can easily change this option by using the argument, \"lemmatize=FALSE,\" to the clean_dyads function below. \u003cbr/\u003e\n\n3. \u003cspan style=\"color:red;\"\u003eSample Size Issue 1: exchange count\u003c/span\u003e: The program derives correlations and AUC for each dyad as metrics of alignment. If there are 40 exchanges (80 turns) between conversation partners, the R value will be computed over 40 data points. For conversations less than about 30 turns, you should not trust the R values that ConversationAlign outputs.  \u003cbr/\u003e\n\n4. \u003cspan style=\"color:red;\"\u003eSample Size Issue 2 \u003c/span\u003e: matching to lookup database: ConversationAlign works by yoking values from a lookup database to each word in your language transcript. Some variables have lots of values characterizing many English words. Other variables (e.g., age of acquisition) only cover about 30k words. When a word in your transcript does not have a 'match' in the lookup datase, ConversationAlign will return an NA which will not go into the average of the words for that interlocutor and turn. This can be dangerous when there are many missing values. Beware! \u003cbr/\u003e\n\n5. \u003cspan style=\"color:red;\"\u003eCompositionality \u003c/span\u003e: ConversationAlign is a caveman in its complexity. It matches a value to each word as if that word is an island. Phenomena like polysemy (e.g., bank) and the modulation of one word by an intensifier (e.g., very terrible) are not handled. This is a problem for many of the affective measures but not for lexical variables like word length. \u003cbr/\u003e\n\n6. \u003cspan style=\"color:red;\"\u003e Resampling for AUC \u003c/span\u003e:  summarize_dyads will output AUC values quantifying the distance between interlocutors on any dimension you specify. AUC will vary depending on the length of the dyad. Therefore, it is often necessary to resample (downsample) your dyads so that they are all of an equivalent length.  This will get very wonky and uninterpretable for very short exchanges. \n\n# Background\nHere are some documents describing how we derived our stopword list and lookup databases.\n\nOur OSF site for this method paper is here:  https://osf.io/atf5q/\n\nRead more about how we created the internal lookup_database for ConversationAlign here:\nhttps://reilly-lab.github.io/ConversationAlign_LookupDb_Methods.pdf\n\nRead more about the variables we have included to align on by linking here:\nhttps://reilly-lab.github.io/ConversationAlign_VariableLookupKey.pdf\n\nYou can read more about the nature of the stopword list and view it here:\nhttps://reilly-lab.github.io/ConversationAlign_StopwordsDb_Methods.pdf\n\n\n# Get in touch!\nContact \u003cjamie_reilly@temple.edu\u003e for feedback and assistance.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freilly-conceptscognitionlab%2Fconversationalign","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Freilly-conceptscognitionlab%2Fconversationalign","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freilly-conceptscognitionlab%2Fconversationalign/lists"}