import%20marimo%0A%0A__generated_with%20%3D%20%220.18.0%22%0Aapp%20%3D%20marimo.App(width%3D%22medium%22)%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%20The%20Complete%20Sherlock%20Holmes%0A%20%20%20%20%23%23%20%5B%23TidyTuesday%5D(https%3A%2F%2Fgithub.com%2Frfordatascience%2Ftidytuesday%2Fblob%2Fmain%2Fdata%2F2025%2F2025-11-18%2Freadme.md)%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20pandas%20as%20pd%0A%20%20%20%20import%20matplotlib.pyplot%20as%20plt%0A%20%20%20%20import%20re%20%23%20regex%0A%20%20%20%20holmes%20%3D%20pd.read_csv('https%3A%2F%2Fraw.githubusercontent.com%2Frfordatascience%2Ftidytuesday%2Fmain%2Fdata%2F2025%2F2025-11-18%2Fholmes.csv')%0A%20%20%20%20return%20holmes%2C%20pd%2C%20re%0A%0A%0A%40app.cell%0Adef%20_(holmes)%3A%0A%20%20%20%20print(holmes.shape)%20%23%20rows%20and%20columns%0A%20%20%20%20print(holmes.head())%20%23%20overview%20of%20data%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(holmes)%3A%0A%20%20%20%20%23%20Count%20number%20of%20books%20(two%20methods)%0A%20%20%20%20holmes.groupby(%22book%22)%0A%20%20%20%20print(holmes%5B%22book%22%5D.nunique())%0A%20%20%20%20%23%20alternative%0A%20%20%20%20print(holmes.groupby(%22book%22).ngroups)%20%23%20ngroups%20tells%20you%20how%20many%20separate%20groups%20were%20created%20by%20the%20groupby.%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(holmes%2C%20re)%3A%0A%20%20%20%20%23%20Pick%20the%20first%20book%20and%20count%20how%20many%20times%20%22Holmes%22%20appears.%0A%20%20%20%20holmes_0%20%3D%20holmes%5Bholmes%5B%22book%22%5D%20%3D%3D%20%22A%20Study%20In%20Scarlet%22%5D%0A%20%20%20%20times_holmes_0%20%3D%20holmes_0%5B%22text%22%5D.str.count(%22Holmes%22%2C%20flags%3Dre.IGNORECASE).sum()%20%23%20it%20seems%20case%20insensitive%0A%20%20%20%20print(times_holmes_0)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(holmes)%3A%0A%20%20%20%20%23%20Count%20the%20number%20of%20books%20with%20the%20string%20%22Moriarty%22%20on%20it%0A%20%20%20%20%23%20Filter%20rows%20containing%20%22Moriarty%22%0A%20%20%20%20line_has_Moriarty%20%3D%20holmes%5Bholmes%5B%22text%22%5D.str.contains(%22Moriarty%22%2C%20na%3DFalse%2C%20case%3DFalse)%5D%0A%20%20%20%20%23%20Group%20by%20book%20and%20get%20unique%20book%20names%0A%20%20%20%20print(line_has_Moriarty%5B%22book%22%5D.nunique())%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(holmes)%3A%0A%20%20%20%20%23%20number%20of%20lines%20per%20book%0A%20%20%20%20lines_per_book%20%3D%20holmes.groupby(%22book%22)%5B'text'%5D.count().sort_values(ascending%3DFalse)%0A%20%20%20%20lines_per_book.plot(kind%3D%22bar%22%2C%20figsize%3D(10%2C4)%2C%20ylabel%3D%22line%20count%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(holmes)%3A%0A%20%20%20%20%23%20total%20word%20count%20per%20book%0A%20%20%20%20holmes%5B%22word_count%22%5D%20%3D%20holmes%5B%22text%22%5D.str.split().str.len()%0A%20%20%20%20words_per_book%20%3D%20holmes.groupby(%22book%22)%5B%22word_count%22%5D.sum().sort_values(ascending%3DFalse)%0A%20%20%20%20print(words_per_book)%0A%20%20%20%20words_per_book.plot(kind%3D%22bar%22%2C%20figsize%3D(10%2C4)%2C%20ylabel%3D%22word%20count%22)%0A%20%20%20%20return%20(words_per_book%2C)%0A%0A%0A%40app.cell%0Adef%20_(holmes%2C%20pd%2C%20re%2C%20words_per_book)%3A%0A%20%20%20%20%23%20Find%20the%20books%20with%20the%20darkest%20content%0A%20%20%20%20%23pattern%20%3D%20r%22death%7Cblood%7Cmurder%7Ckill%7Cslaughter%7Chorror%22%0A%20%20%20%20pattern%20%3D%20r%22death%7Cblood%7Cmurder%7Ckill%7Cslaughter%7Chorror%7Ccorpse%7Cgrave%7Cfuneral%7Cpoison%7Cassassin%7Ccrime%7Cattack%7Cthreat%7Cviolence%7Cfear%7Cpanic%7Cdanger%7Cdarkness%7Cterror%7Cchill%7Csinister%7Cgloom%7Cmenace%7Ctrap%7Cvictim%22%0A%20%20%20%20%23print(holmes%5B%22text%22%5D.str.count(pattern%2C%20flags%3Dre.IGNORECASE).sum())%0A%20%20%20%20dark_words_per_book%20%3D%20holmes.groupby(%22book%22)%5B%22text%22%5D.apply(lambda%20x%3A%20x.str.count(pattern%2C%20flags%3Dre.IGNORECASE).sum())%0A%20%20%20%20dark_dict%20%3D%20%7B%22total_words%22%3Awords_per_book%2C%20%22dark_count%22%3Adark_words_per_book%7D%0A%20%20%20%20dark_df%20%3D%20pd.DataFrame(dark_dict)%0A%20%20%20%20dark_normalised%20%3D%20dark_df%5B%22dark_count%22%5D%2Fdark_df%5B%22total_words%22%5D*1000%0A%20%20%20%20top_dark%20%3D%20dark_normalised.sort_values(ascending%3DFalse)%0A%20%20%20%20top_dark.plot(kind%3D%22bar%22%2C%20title%20%3D%20%22Stories%20by%20number%20of%20dark%20words%22%2C%20ylabel%20%3D%20%22count%20per%201000%20words%22%2C%20figsize%3D(10%2C4))%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20return%20(mo%2C)%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
5eaf26679f73584dc7d66fc1936e1050