From ccab72aa0f1cae5430f3ceec0388d4c41b4d724f Mon Sep 17 00:00:00 2001 From: Andreas Gammelgaard Damsbo Date: Fri, 8 Nov 2024 15:13:33 +0100 Subject: [PATCH] Initial commit --- .Rbuildignore | 6 + .Rprofile | 1 + .gitignore | 7 + DESCRIPTION | 26 + LICENSE.md | 659 +++++++ NAMESPACE | 10 + R/baseline_table.R | 22 + R/helpers.R | 110 ++ R/regression_model.R | 99 + R/regression_table.R | 40 + README.md | 20 + analyses.qmd | 53 + app/functions.R | 282 +++ .../shinyapps.io/agdamsbo/webResearch.dcf | 10 + app/server.R | 116 ++ app/ui.R | 124 ++ data.Rds | Bin 0 -> 1681 bytes man/baseline_table.Rd | 32 + man/file_extension.Rd | 21 + man/getfun.Rd | 20 + man/read_input.Rd | 22 + man/regression_model.Rd | 54 + man/regression_table.Rd | 45 + man/write_quarto.Rd | 31 + publish_shiny.R | 15 + renv.lock | 1730 +++++++++++++++++ renv/.gitignore | 7 + renv/activate.R | 1305 +++++++++++++ toPdfViaTempFile14132-0.html | 1658 ++++++++++++++++ toPdfViaTempFile14132-1.pdf | 0 webResearch.Rproj | 22 + 31 files changed, 6547 insertions(+) create mode 100644 .Rbuildignore create mode 100644 .Rprofile create mode 100644 .gitignore create mode 100644 DESCRIPTION create mode 100644 LICENSE.md create mode 100644 NAMESPACE create mode 100644 R/baseline_table.R create mode 100644 R/helpers.R create mode 100644 R/regression_model.R create mode 100644 R/regression_table.R create mode 100644 README.md create mode 100644 analyses.qmd create mode 100644 app/functions.R create mode 100644 app/rsconnect/shinyapps.io/agdamsbo/webResearch.dcf create mode 100644 app/server.R create mode 100644 app/ui.R create mode 100644 data.Rds create mode 100644 man/baseline_table.Rd create mode 100644 man/file_extension.Rd create mode 100644 man/getfun.Rd create mode 100644 man/read_input.Rd create mode 100644 man/regression_model.Rd create mode 100644 man/regression_table.Rd create mode 100644 man/write_quarto.Rd create mode 100644 publish_shiny.R create mode 100644 renv.lock create mode 100644 renv/.gitignore create mode 100644 renv/activate.R create mode 100644 toPdfViaTempFile14132-0.html create mode 100644 toPdfViaTempFile14132-1.pdf create mode 100644 webResearch.Rproj diff --git a/.Rbuildignore b/.Rbuildignore new file mode 100644 index 0000000..ce430ed --- /dev/null +++ b/.Rbuildignore @@ -0,0 +1,6 @@ +^renv$ +^renv\.lock$ +^webResearch\.Rproj$ +^\.Rproj\.user$ +^LICENSE\.md$ +^dev$ diff --git a/.Rprofile b/.Rprofile new file mode 100644 index 0000000..81b960f --- /dev/null +++ b/.Rprofile @@ -0,0 +1 @@ +source("renv/activate.R") diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5fc2453 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +.Rproj.user +dev/ +.Rhistory +.Rdata +.httr-oauth +.DS_Store +.quarto diff --git a/DESCRIPTION b/DESCRIPTION new file mode 100644 index 0000000..869e9fb --- /dev/null +++ b/DESCRIPTION @@ -0,0 +1,26 @@ +Package: webResearch +Title: Browser Based Data Analysis +Version: 0.0.0.9000 +Authors@R: + person("Andreas Gammelgaard", "Damsbo", , "agdamsbo@clin.au.dk", role = c("aut", "cre"), + comment = c(ORCID = "0000-0002-7559-1154")) +Description: Browser based basic data analysis and research output. +License: AGPL (>= 3) +Encoding: UTF-8 +Roxygen: list(markdown = TRUE) +RoxygenNote: 7.3.2 +Imports: + assertthat, + dplyr, + glue, + gt, + gtsummary, + haven, + here, + openxlsx2, + quarto, + readODS, + readr +Suggests: + MASS, + styler diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..fab6548 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,659 @@ +GNU Affero General Public License +================================= + +_Version 3, 19 November 2007_ +_Copyright (C) 2007 Free Software Foundation, Inc. <>_ + +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. + +## Preamble + +The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + +The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains +free software for all its users. + +When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + +Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + +A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + +The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + +An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing +under this license. + +The precise terms and conditions for copying, distribution and +modification follow. + +## TERMS AND CONDITIONS + +### 0. Definitions. + +"This License" refers to version 3 of the GNU Affero General Public +License. + +"Copyright" also means copyright-like laws that apply to other kinds +of works, such as semiconductor masks. + +"The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + +To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of +an exact copy. The resulting work is called a "modified version" of +the earlier work or a work "based on" the earlier work. + +A "covered work" means either the unmodified Program or a work based +on the Program. + +To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + +To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user +through a computer network, with no transfer of a copy, is not +conveying. + +An interactive user interface displays "Appropriate Legal Notices" to +the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + +### 1. Source Code. + +The "source code" for a work means the preferred form of the work for +making modifications to it. "Object code" means any non-source form of +a work. + +A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + +The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + +The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + +The Corresponding Source need not include anything that users can +regenerate automatically from other parts of the Corresponding Source. + +The Corresponding Source for a work in source code form is that same +work. + +### 2. Basic Permissions. + +All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + +You may make, run and propagate covered works that you do not convey, +without conditions so long as your license otherwise remains in force. +You may convey covered works to others for the sole purpose of having +them make modifications exclusively for you, or provide you with +facilities for running those works, provided that you comply with the +terms of this License in conveying all material for which you do not +control copyright. Those thus making or running the covered works for +you must do so exclusively on your behalf, under your direction and +control, on terms that prohibit them from making any copies of your +copyrighted material outside their relationship with you. + +Conveying under any other circumstances is permitted solely under the +conditions stated below. Sublicensing is not allowed; section 10 makes +it unnecessary. + +### 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + +No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + +When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such +circumvention is effected by exercising rights under this License with +respect to the covered work, and you disclaim any intention to limit +operation or modification of the work as a means of enforcing, against +the work's users, your or third parties' legal rights to forbid +circumvention of technological measures. + +### 4. Conveying Verbatim Copies. + +You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + +You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + +### 5. Conveying Modified Source Versions. + +You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these +conditions: + +- a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. +- b) The work must carry prominent notices stating that it is + released under this License and any conditions added under + section 7. This requirement modifies the requirement in section 4 + to "keep intact all notices". +- c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. +- d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + +A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + +### 6. Conveying Non-Source Forms. + +You may convey a covered work in object code form under the terms of +sections 4 and 5, provided that you also convey the machine-readable +Corresponding Source under the terms of this License, in one of these +ways: + +- a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. +- b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the Corresponding + Source from a network server at no charge. +- c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. +- d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. +- e) Convey the object code using peer-to-peer transmission, + provided you inform other peers where the object code and + Corresponding Source of the work are being offered to the general + public at no charge under subsection 6d. + +A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + +A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, +family, or household purposes, or (2) anything designed or sold for +incorporation into a dwelling. In determining whether a product is a +consumer product, doubtful cases shall be resolved in favor of +coverage. For a particular product received by a particular user, +"normally used" refers to a typical or common use of that class of +product, regardless of the status of the particular user or of the way +in which the particular user actually uses, or expects or is expected +to use, the product. A product is a consumer product regardless of +whether the product has substantial commercial, industrial or +non-consumer uses, unless such uses represent the only significant +mode of use of the product. + +"Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to +install and execute modified versions of a covered work in that User +Product from a modified version of its Corresponding Source. The +information must suffice to ensure that the continued functioning of +the modified object code is in no case prevented or interfered with +solely because modification has been made. + +If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + +The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or +updates for a work that has been modified or installed by the +recipient, or for the User Product in which it has been modified or +installed. Access to a network may be denied when the modification +itself materially and adversely affects the operation of the network +or violates the rules and protocols for communication across the +network. + +Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + +### 7. Additional Terms. + +"Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + +When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + +Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders +of that material) supplement the terms of this License with terms: + +- a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or +- b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or +- c) Prohibiting misrepresentation of the origin of that material, + or requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or +- d) Limiting the use for publicity purposes of names of licensors + or authors of the material; or +- e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or +- f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions + of it) with contractual assumptions of liability to the recipient, + for any liability that these contractual assumptions directly + impose on those licensors and authors. + +All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + +If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + +Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; the +above requirements apply either way. + +### 8. Termination. + +You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + +However, if you cease all violation of this License, then your license +from a particular copyright holder is reinstated (a) provisionally, +unless and until the copyright holder explicitly and finally +terminates your license, and (b) permanently, if the copyright holder +fails to notify you of the violation by some reasonable means prior to +60 days after the cessation. + +Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + +Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + +### 9. Acceptance Not Required for Having Copies. + +You are not required to accept this License in order to receive or run +a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + +### 10. Automatic Licensing of Downstream Recipients. + +Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + +An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + +You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + +### 11. Patents. + +A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + +A contributor's "essential patent claims" are all patent claims owned +or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + +Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + +In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + +If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + +If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + +A patent license is "discriminatory" if it does not include within the +scope of its coverage, prohibits the exercise of, or is conditioned on +the non-exercise of one or more of the rights that are specifically +granted under this License. You may not convey a covered work if you +are a party to an arrangement with a third party that is in the +business of distributing software, under which you make payment to the +third party based on the extent of your activity of conveying the +work, and under which the third party grants, to any of the parties +who would receive the covered work from you, a discriminatory patent +license (a) in connection with copies of the covered work conveyed by +you (or copies made from those copies), or (b) primarily for and in +connection with specific products or compilations that contain the +covered work, unless you entered into that arrangement, or that patent +license was granted, prior to 28 March 2007. + +Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + +### 12. No Surrender of Others' Freedom. + +If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under +this License and any other pertinent obligations, then as a +consequence you may not convey it at all. For example, if you agree to +terms that obligate you to collect a royalty for further conveying +from those to whom you convey the Program, the only way you could +satisfy both those terms and this License would be to refrain entirely +from conveying the Program. + +### 13. Remote Network Interaction; Use with the GNU General Public License. + +Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your +version supports such interaction) an opportunity to receive the +Corresponding Source of your version by providing access to the +Corresponding Source from a network server at no charge, through some +standard or customary means of facilitating copying of software. This +Corresponding Source shall include the Corresponding Source for any +work covered by version 3 of the GNU General Public License that is +incorporated pursuant to the following paragraph. + +Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + +### 14. Revised Versions of this License. + +The Free Software Foundation may publish revised and/or new versions +of the GNU Affero General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever +published by the Free Software Foundation. + +If the Program specifies that a proxy can decide which future versions +of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + +Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + +### 15. Disclaimer of Warranty. + +THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT +WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND +PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE +DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR +CORRECTION. + +### 16. Limitation of Liability. + +IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR +CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES +ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT +NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR +LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM +TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER +PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +### 17. Interpretation of Sections 15 and 16. + +If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + +END OF TERMS AND CONDITIONS + +## How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these +terms. + +To do so, attach the following notices to the program. It is safest to +attach them to the start of each source file to most effectively state +the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper +mail. + +If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for +the specific requirements. + +You should also get your employer (if you work as a programmer) or +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. For more information on this, and how to apply and follow +the GNU AGPL, see . diff --git a/NAMESPACE b/NAMESPACE new file mode 100644 index 0000000..cb89686 --- /dev/null +++ b/NAMESPACE @@ -0,0 +1,10 @@ +# Generated by roxygen2: do not edit by hand + +export(baseline_table) +export(file_extension) +export(getfun) +export(read_input) +export(regression_model) +export(regression_table) +export(write_quarto) +importFrom(stats,as.formula) diff --git a/R/baseline_table.R b/R/baseline_table.R new file mode 100644 index 0000000..28629ba --- /dev/null +++ b/R/baseline_table.R @@ -0,0 +1,22 @@ +#' Print a flexible baseline characteristics table +#' +#' @param data data set +#' @param fun.args list of arguments passed to +#' @param fun function to +#' @param vars character vector of variables to include +#' +#' @return object of standard class for fun +#' @export +#' +#' @examples +#' mtcars |> baseline_table() +#' mtcars |> baseline_table(fun.args = list(by = "gear")) +baseline_table <- function(data, fun.args = NULL, fun = gtsummary::tbl_summary, vars = NULL) { + if (!is.null(vars)) { + data <- dplyr::select(dplyr::all_of(vars)) + } + + out <- do.call(fun, c(list(data = data), fun.args)) + return(out) +} + diff --git a/R/helpers.R b/R/helpers.R new file mode 100644 index 0000000..cbb7542 --- /dev/null +++ b/R/helpers.R @@ -0,0 +1,110 @@ +#' Wrapper function to get function from character vector referring to function from namespace. Passed to 'do.call()' +#' +#' @description +#' This function follows the idea from this comment: https://stackoverflow.com/questions/38983179/do-call-a-function-in-r-without-loading-the-package +#' @param x function or function name +#' +#' @return function or character vector +#' @export +#' +#' @examples +#' getfun("stats::lm") +getfun <- function(x) { + if("character" %in% class(x)){ + if (length(grep("::", x)) > 0) { + parts <- strsplit(x, "::")[[1]] + requireNamespace(parts[1]) + getExportedValue(parts[1], parts[2]) + } + }else { + x + } +} + +#' Wrapper to save data in RDS, load into specified qmd and render +#' +#' @param data list to pass to qmd +#' @param fileformat output format. Ignored if file!=NULL +#' @param qmd.file qmd file to render. Default is 'here::here("analyses.qmd")' +#' @param file exact filename (Optional) +#' @param ... Ignored for now +#' +#' @return none +#' @export +#' +write_quarto <- function(data,fileformat,qmd.file=here::here("analyses.qmd"),file=NULL,...){ + if (is.null(file)){ + file <- paste0("analyses.",fileformat) + } + temp <- tempfile(fileext = ".Rds") + # write_rds(mtcars, temp) + # read_rds(temp) + web_data <- data + saveRDS(web_data,file=temp) + + quarto::quarto_render(qmd.file, + output_file = file, + execute_params = list(data.file=temp) + ) +} + +#' Helper to import files correctly +#' +#' @param filenames file names +#' +#' @return character vector +#' @export +#' +#' @examples +#' file_extension(list.files(here::here(""))[[2]])[[1]] +#' file_extension(c("file.cd..ks", "file")) +file_extension <- function(filenames) { + sub( + pattern = "^(.*\\.|[^.]+)(?=[^.]*)", replacement = "", + filenames, + perl = TRUE + ) +} + +#' Flexible file import based on extension +#' +#' @param file file name +#' @param consider.na character vector of strings to consider as NAs +#' +#' @return tibble +#' @export +#' +#' @examples +#' read_input("https://raw.githubusercontent.com/agdamsbo/cognitive.index.lookup/main/data/sample.csv") +read_input <- function(file, consider.na = c("NA", '""', "")) { + ext <- file_extension(file) + + if (ext == "csv") { + df <- readr::read_csv(file = file, na = consider.na) + } else if (ext %in% c("xls", "xlsx")) { + df <- openxlsx2::read_xlsx(file = file, na.strings = consider.na) + } else if (ext == "dta") { + df <- haven::read_dta(file = file) + } else if (ext == "ods") { + df <- readODS::read_ods(file = file) + } else { + stop("Input file format has to be on of: + '.csv', '.xls', '.xlsx', '.dta' or '.ods'") + } + + df +} + +#' Convert string of arguments to list of arguments +#' +#' @description +#' Idea from the answer: https://stackoverflow.com/a/62979238 +#' +#' @param string string to convert to list to use with do.call +#' +#' @return list +#' @export +#' +argsstring2list <- function(string){ + eval(parse(text = paste0("list(", string, ")"))) +} diff --git a/R/regression_model.R b/R/regression_model.R new file mode 100644 index 0000000..602f782 --- /dev/null +++ b/R/regression_model.R @@ -0,0 +1,99 @@ +#' Print a flexible baseline characteristics table +#' +#' @param data data set +#' @param fun Name of function as character vector or function to use for model creation. +#' @param vars character vector of variables to include +#' @param outcome.str Name of outcome variable. Character vector. +#' @param auto.mode Make assumptions on function dependent on outcome data format. +#' @param formula.str Formula as string. Passed through 'glue::glue'. If given, 'outcome.str' and 'vars' are ignored. Optional. +#' @param args.list List of arguments passed to 'fun' with 'do.call'. +#' +#' @importFrom stats as.formula +#' +#' @return object of standard class for fun +#' @export +#' +#' @examples +#' gtsummary::trial |> +#' regression_model(outcome.str = "age") +#' gtsummary::trial |> +#' regression_model( +#' outcome.str = "age", +#' fun = "stats::lm", +#' formula.str = "{outcome.str}~.", +#' args.list = NULL +#' ) +#' gtsummary::trial |> regression_model( +#' outcome.str = "trt", +#' fun = "stats::glm", +#' args.list = list(family = binomial(link = "logit")) +#' ) +regression_model <- function(data, + outcome.str, + auto.mode = TRUE, + formula.str = NULL, + args.list = NULL, + fun = NULL, + vars = NULL) { + if (!is.null(formula.str)) { + formula.str <- glue::glue(formula.str) + } else { + assertthat::assert_that(outcome.str %in% names(data), + msg = "Outcome variable is not present in the provided dataset" + ) + formula.str <- glue::glue("{outcome.str}~.") + + if (!is.null(vars)) { + if (outcome.str %in% vars){ + vars <- vars[vars %in% outcome.str] + } + data <- data |> dplyr::select(dplyr::all_of(c(vars,outcome.str))) + } + } + + # Formatting character variables as factor + # Improvement should add a missing vector to format as NA + data <- data |> dplyr::mutate(dplyr::across(dplyr::where(is.character), as.factor)) + + # browser() + if (auto.mode) { + if (is.numeric(data[[outcome.str]])){ + fun <- "stats::lm" + } else if (is.factor(data[[outcome.str]])){ + if (length(levels(data[[outcome.str]]))==2){ + fun <- "stats::glm" + args.list = list(family = binomial(link = "logit")) + + } else if (length(levels(data[[outcome.str]]))>2){ + fun <- "MASS::polr" + args.list = list( + Hess = TRUE, + method = "logistic" + ) + } else { + stop("The provided output variable only has one level") + } + } else { + stop("Output variable should be either numeric or factor for auto.mode") + } + + } + + assertthat::assert_that("character" %in% class(fun), + msg = "Please provide the function as a character vector." + ) + + out <- do.call( + getfun(fun), + c( + list(data = data), + list(formula = as.formula(formula.str)), + args.list + ) + ) + + # Recreating the call + # out$call <- match.call(definition=eval(parse(text=fun)), call(fun, data = 'data',formula = as.formula(formula.str),args.list)) + + return(out) +} diff --git a/R/regression_table.R b/R/regression_table.R new file mode 100644 index 0000000..c1639fb --- /dev/null +++ b/R/regression_table.R @@ -0,0 +1,40 @@ +#' Create table of regression model +#' +#' @param data regression model +#' @param args.list list of arguments passed to 'fun'. +#' @param fun function to use for table creation. Default is "gtsummary::tbl_regression". +#' +#' @return object of standard class for fun +#' @export +#' +#' @examples +#' gtsummary::trial |> +#' regression_model( +#' outcome.str = "stage", +#' fun = "MASS::polr" +#' ) |> +#' regression_table(args.list = list(exponentiate = TRUE)) +#' gtsummary::trial |> +#' regression_model( +#' outcome.str = "age", +#' fun = "stats::lm", +#' formula.str = "{outcome.str}~.", +#' args.list = NULL +#' ) |> +#' regression_table() +#' gtsummary::trial |> +#' regression_model( +#' outcome.str = "trt", +#' fun = "stats::glm", +#' args.list = list(family = binomial(link = "logit")) +#' ) |> +#' regression_table() +regression_table <- function(data, args.list = NULL, fun = "gtsummary::tbl_regression") { + + if (any(c(length(class(data))!=1, class(data)!="lm"))){ + args.list <- c(args.list,list(exponentiate=TRUE)) + } + + out <- do.call(getfun(fun), c(list(x = data), args.list)) + return(out) +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..05366f4 --- /dev/null +++ b/README.md @@ -0,0 +1,20 @@ +# webResearch + + + + + +This package is the backbone of the open and freely accessible browser-based data analysis tool with project name "webResearch". + +## Road map + +- A minimally working example + + - Table 1 of baseline characteristics + - Table 2 of main analysis results + - Figure 1 of main results (like forest plot) + - Shiny GUI implementation + +- Fundraising for further development + +- Implementation with different focus groups and educational formats. diff --git a/analyses.qmd b/analyses.qmd new file mode 100644 index 0000000..2c0ab49 --- /dev/null +++ b/analyses.qmd @@ -0,0 +1,53 @@ +--- +title: "webResearch analysis results" +date: today +execute: + echo: false +params: + data.file: NA +--- + + + + + + + + + + + + +```{r setup} +web_data <- readRDS(file = params$data.file) +# readr::read_rds(file = here::here("data.Rds")) +library(gtsummary) +library(gt) +``` + +## Introduction + + + +## Methods + + +Analyses were conducted in R version `r paste(version["major"],version["minor"],sep=".")` using the web-based data analysis tool 'webResearcher' version `r packageVersion("webResearch")`. + +## Results + +Below is the baseline characteristics plotted. + +```{r} +web_data$table1 +``` + +Here are the regression results. + +```{r} +web_data$table2 +``` + +## Discussion + +Good luck on your further work! diff --git a/app/functions.R b/app/functions.R new file mode 100644 index 0000000..2541691 --- /dev/null +++ b/app/functions.R @@ -0,0 +1,282 @@ + + +######## +#### Current file: R//baseline_table.R +######## + + + + + + + + + + + + + + +baseline_table <- function(data, fun.args = NULL, fun = gtsummary::tbl_summary, vars = NULL) { + if (!is.null(vars)) { + data <- dplyr::select(dplyr::all_of(vars)) + } + + out <- do.call(fun, c(list(data = data), fun.args)) + return(out) +} + + + +######## +#### Current file: R//helpers.R +######## + + + + + + + + + + + + +getfun <- function(x) { + if("character" %in% class(x)){ + if (length(grep("::", x)) > 0) { + parts <- strsplit(x, "::")[[1]] + requireNamespace(parts[1]) + getExportedValue(parts[1], parts[2]) + } + }else { + x + } +} + + + + + + + + + + + + +write_quarto <- function(data,fileformat,qmd.file=here::here("analyses.qmd"),file=NULL,...){ + if (is.null(file)){ + file <- paste0("analyses.",fileformat) + } + temp <- tempfile(fileext = ".Rds") + # write_rds(mtcars, temp) + # read_rds(temp) + web_data <- data + saveRDS(web_data,file=temp) + + quarto::quarto_render(qmd.file, + output_file = file, + execute_params = list(data.file=temp) + ) +} + + + + + + + + + + + +file_extension <- function(filenames) { + sub( + pattern = "^(.*\\.|[^.]+)(?=[^.]*)", replacement = "", + filenames, + perl = TRUE + ) +} + + + + + + + + + + + +read_input <- function(file, consider.na = c("NA", '""', "")) { + ext <- file_extension(file) + + if (ext == "csv") { + df <- readr::read_csv(file = file, na = consider.na) + } else if (ext %in% c("xls", "xlsx")) { + df <- openxlsx2::read_xlsx(file = file, na.strings = consider.na) + } else if (ext == "dta") { + df <- haven::read_dta(file = file) + } else if (ext == "ods") { + df <- readODS::read_ods(file = file) + } else { + stop("Input file format has to be on of: + '.csv', '.xls', '.xlsx', '.dta' or '.ods'") + } + + df +} + + + +######## +#### Current file: R//regression_model.R +######## + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +regression_model <- function(data, + outcome.str, + auto.mode = TRUE, + formula.str = NULL, + args.list = NULL, + fun = NULL, + vars = NULL) { + if (!is.null(formula.str)) { + formula.str <- glue::glue(formula.str) + } else { + assertthat::assert_that(outcome.str %in% names(data), + msg = "Outcome variable is not present in the provided dataset" + ) + formula.str <- glue::glue("{outcome.str}~.") + + if (!is.null(vars)) { + if (outcome.str %in% vars){ + vars <- vars[vars %in% outcome.str] + } + data <- data |> dplyr::select(dplyr::all_of(c(vars,outcome.str))) + } + } + + # Formatting character variables as factor + # Improvement should add a missing vector to format as NA + data <- data |> dplyr::mutate(dplyr::across(dplyr::where(is.character), as.factor)) + + # browser() + if (auto.mode) { + if (is.numeric(data[[outcome.str]])){ + fun <- "stats::lm" + } else if (is.factor(data[[outcome.str]])){ + if (length(levels(data[[outcome.str]]))==2){ + fun <- "stats::glm" + args.list = list(family = binomial(link = "logit")) + + } else if (length(levels(data[[outcome.str]]))>2){ + fun <- "MASS::polr" + args.list = list( + Hess = TRUE, + method = "logistic" + ) + } else { + stop("The provided output variable only has one level") + } + } else { + stop("Output variable should be either numeric or factor for auto.mode") + } + + } + + assertthat::assert_that("character" %in% class(fun), + msg = "Please provide the function as a character vector." + ) + + out <- do.call( + getfun(fun), + c( + list(data = data), + list(formula = as.formula(formula.str)), + args.list + ) + ) + + # Recreating the call + # out$call <- match.call(definition=eval(parse(text=fun)), call(fun, data = 'data',formula = as.formula(formula.str),args.list)) + + return(out) +} + + +######## +#### Current file: R//regression_table.R +######## + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +regression_table <- function(data, args.list = NULL, fun = "gtsummary::tbl_regression") { + + if (any(c(length(class(data))!=1, class(data)!="lm"))){ + args.list <- c(args.list,list(exponentiate=TRUE)) + } + + out <- do.call(getfun(fun), c(list(x = data), args.list)) + return(out) +} diff --git a/app/rsconnect/shinyapps.io/agdamsbo/webResearch.dcf b/app/rsconnect/shinyapps.io/agdamsbo/webResearch.dcf new file mode 100644 index 0000000..0516923 --- /dev/null +++ b/app/rsconnect/shinyapps.io/agdamsbo/webResearch.dcf @@ -0,0 +1,10 @@ +name: webResearch +title: +username: agdamsbo +account: agdamsbo +server: shinyapps.io +hostUrl: https://api.shinyapps.io/v1 +appId: 13276335 +bundleId: 9334284 +url: https://agdamsbo.shinyapps.io/webResearch/ +version: 1 diff --git a/app/server.R b/app/server.R new file mode 100644 index 0000000..2360550 --- /dev/null +++ b/app/server.R @@ -0,0 +1,116 @@ +# project.aid::merge_scripts(list.files("R/",full.names = TRUE),dest = here::here("app/functions.R")) +source(here::here("app/functions.R")) + +server <- function(input, output, session) { + v <- shiny::reactiveValues( + list = NULL, + ds = NULL + ) + + ds <- shiny::reactive({ + # input$file1 will be NULL initially. After the user selects + # and uploads a file, head of that data file by default, + # or all rows if selected, will be shown. + + shiny::req(input$file) + + v$ds <- "present" + return(read_input(input$file$datapath)) + }) + + output$include_vars <- shiny::renderUI({ + selectizeInput( + inputId = "include_vars", + selected = NULL, + label = "Covariables to include", + choices = colnames(ds()), + multiple = TRUE + ) + }) + + output$outcome_var <- shiny::renderUI({ + selectInput( + inputId = "outcome_var", + selected = NULL, + label = "Select outcome variable", + choices = colnames(ds()), + multiple = FALSE + ) + }) + + output$data.input <- shiny::renderTable({ + shiny::req(input$file) + ds() + }) + + shiny::observeEvent( + { + input$load + }, + { + shiny::req(input$outcome_var) + + v$list <- ds() |> + (\(data){ + # browser() + list( + data = data, + table1 = data |> baseline_table(), + table2 = data |> + regression_model( + outcome.str = input$outcome_var, + auto.mode = input$regression_auto == 1, + formula.str = input$regression_formula, + fun = input$regression_fun, + args.list = eval(parse(text = paste0("list(", input$regression_args, ")"))), + vars = input$include_vars + ) |> + regression_table() + ) + })() + + output$table1 <- gt::render_gt( + v$list$table1 |> + gtsummary::as_gt() + ) + + output$table2 <- gt::render_gt( + v$list$table2 |> + gtsummary::as_gt() + ) + + } + ) + + + output$uploaded <- shiny::reactive({ + if (is.null(v$ds)) { + "no" + } else { + "yes" + } + }) + + shiny::outputOptions(output, "uploaded", suspendWhenHidden = FALSE) + + ##### + #### Generating output + ##### + + # Downloadable csv of selected dataset ---- + # output$downloadData <- shiny::downloadHandler( + # filename = "index_lookup.csv", + # content = function(file) { + # write.csv(v$index, file, row.names = FALSE) + # } + # ) + + output$report <- downloadHandler( + filename = "analyses.html", + content = function(file) { + v$list |> write_quarto(file = file) + } + ) + + # +} diff --git a/app/ui.R b/app/ui.R new file mode 100644 index 0000000..297f685 --- /dev/null +++ b/app/ui.R @@ -0,0 +1,124 @@ +require(shiny) +require(bslib) +# require(ggplot2) +# source("https://raw.githubusercontent.com/agdamsbo/cognitive.index.lookup/main/R/index_from_raw.R") +# source("https://raw.githubusercontent.com/agdamsbo/cognitive.index.lookup/main/R/plot_index.R") +# source(here::here("R/index_from_raw.R")) +# source(here::here("R/plot_index.R")) + +# ui <- fluidPage( + +cards <- list( + bslib::card( + max_height = "200px", + full_screen = TRUE, + bslib::card_header("Data overview"), + shiny::uiOutput("data.input") + ), + bslib::card( + # max_height = "200px", + full_screen = TRUE, + bslib::card_header("Baseline characteristics"), + gt::gt_output(outputId = "table1") + ), + bslib::card( + full_screen = TRUE, + bslib::card_header("Multivariable regression table"), + gt::gt_output(outputId = "table2") + ) +) + + +ui <- bslib::page_sidebar( + theme = bslib::bs_theme(bootswatch = "minty"), + title = "webResearcher for easy data analysis", + window_title = "webResearcher", + header = h6("Welcome to the webResearcher tool. This is an early alpha version to act as a proof-of-concept and in no way intended for wider public use."), + + # sidebarPanel( + sidebar = bslib::sidebar( + open = "open", + h4("Upload your dataset"), + + # Input: Select a file ---- + fileInput( + inputId = "file", + label = "Choose data file", + multiple = FALSE, + accept = c( + "text/csv", + "text/comma-separated-values,text/plain", + ".csv", + ".xlsx", + ".xls", + ".dta", + ".ods" + ) + ), + conditionalPanel( + condition = "output.uploaded=='yes'", + h4("Parameter specifications"), + radioButtons( + inputId = "regression_auto", + label = "Automatically choose function", + inline = TRUE, + choiceNames = c( + "Yes", + "No" + ), + choiceValues = c(1, 2) + ), + conditionalPanel( + condition = "input.regression_auto==2", + textInput( + inputId = "regression_formula", + label = "Formula string to render with 'glue::glue'", + value = "{outcome.str}~." + ), + textInput( + inputId = "regression_fun", + label = "Function to use for analysis (needs pasckage and name)", + value = "stats::lm" + ), + textInput( + inputId = "regression_args", + label = "Arguments to pass to the function (provided as a string)", + value = "" + ) + ), + helpText(em("Please specify relevant columns from your data, and press 'Load data'")), + uiOutput("outcome_var"), + radioButtons( + inputId = "all", + label = "Specify covariables", + inline = TRUE, selected = 2, + choiceNames = c( + "Yes", + "No" + ), + choiceValues = c(1, 2) + ), + conditionalPanel( + condition = "input.all==1", + uiOutput("include_vars") + ), + actionButton("load", "Analyse", class = "btn-primary") + ) + # , + + # Horizontal line ---- + # tags$hr(), + # h4("Download results"), + # + # # Button + # downloadButton(outputId="report", + # label= "Download", + # icon = shiny::icon("download")) + ), + layout_columns( + cards[[1]] + ), + layout_columns( + cards[[2]], cards[[3]] + ) +) diff --git a/data.Rds b/data.Rds new file mode 100644 index 0000000000000000000000000000000000000000..6b3ee4e54fab6d0cbcd156a3daeb611f37abf4f5 GIT binary patch literal 1681 zcmV;C25$KuiwFP!000001GQP{Zrer>ULDru+mvgvI*!A?y3$`}^zH7>mdF$-mr2xs9+mOLH4Hw0)i157PD6LCxYOK`uqs z`5)mk*tpolM=7pPH{MiCDRM}&HX7G!#=dUYO`2%kBRs8Ds~bX+NS;9sCOIV!G~3oq z!$Wq$s+qRFLxLfaO>nG3{Ckc8j%AGBKw&Z9DMwyp<(NS&!X`Q9I8q!%Q7lJJsD|$} zM?Xgv*9si-$hpL!ie4bcFvlZk7y-{Hc(OQt25niyh#Ia#TMn8gp(Rf^L@k?yPmG;` z|5<37K`pb0pO$hvbqTJ=g!dWY6)_58=25RWULePdI9Abv9LD3QT}6${sBwkkZ|Gfv z_I2=|hwjh7EA(H0{tc4n9P(V`c)_vC@hkLP^x^&-+*duguMqCb0KcKwkKm4BUj9Um zP0Xp#dkOUkpPL-NVQdQ;H>EieTE0ZyTj=>8KAP`B^H=b{Lv-Fo&U+lcBkn%pzJ`5> z_-_#ZAVAY&_&g$-oHg+mbFZ~^@IHloMtb@jJWp8j-gDNAIR1_`?=^A1GDe;}zaWtq z_y>btj?v0%$ur_dS&$r~K90%#ie*)dUE(fA>u~!>tTRq%(se0K%uo5vb>_+tl_TRm zkty4Jdsnl|dmakiPiE7snIP-)BYS;ll-6Q2>UPRK%nCNAY3ACwYAWdF2};EZ+n%Cal=p{;u`1hpvBp+)`f z@qT%Hz(>(Q#o8$EX{J`@U#cNB4TkK>kdKDsj((t-RyQs2k}>Q@`?F>m?weP*kNCK! zc6Gk7II`(OgfaKxQI;&FTr=M2VxOVdHKo-$#j?$lxki0*C9LO%wXWAdD{7~0; zHugC0SnDIVWsC*Rj(n2@wmYc(bCW7JRc!y2l439m!t5Kc+h9I^)-=V$nN8`_aBEQBAYJStXMoPuE$W6p5;C z?Am*h_l%EseAml^QN<*4y4(C8FvzYoZbmn~H{>(|i2mOK5dJQZ{9 z$T@jjagQrOUs;it-nAB-b<|6FLF=r*g4fx+Ut6}Mwj=|~+72mefd#I~z+};qS2n@A z=w{6Yv0UJbvZ|H&v)|Nr538D~=tl>p&i9BlL&1xwqHe3otG9}xmP*@dzzm4wOC360 zWWmcwW!*2M^!87s(#z7eyxHveakLy_K7{`Y^IkSFzAFmQ9X~1AHJ&JyLKY>&tg`N> z{c3C4Ri3CZyJ{n+s#J`CrQjipgMe5%@-{9y)vWpl5_kB99-#=NR$F z7~{u7b)1Vg6!A?xh-0zg%(nd+?>-T1GaP^J8*BK#Yx@E2-<8T$%@SYsBjn;pyWiGB zV@E%NSXsmhA&w!rcmo;-V$EcYmzNKOBhtB;Mhuyu5jrCdCu6<6Fm-57vEF4rytv3G z6c^7uTyNT_Gm+@Um~);47v*ccbdhF_b=Z)46Ho{86Je`s$4DYnGNn!#_;)WS}Px{(1Cd2D*wwXCLC5d0F1kKy`HUM&sm8Nx5f` zo92uo=V$QhbIM|fKN}nna;dD@n@L(?T*(y<@9H)c|Pr&XVDkjl?m9C zGd=-34m$~(ht0vBX~xYtac7(7igP~0POhEC2Cj?AO;VE6n%oHXzY%P{1^+bc9IWCc z`ejJb$|;H#e6z4qQl5F(f`{nl?p2H~z%F`t^|U(`WJOrjgVeQa4AVFDl>4^Sj9Ya0 zS3JZzTSfVLdy5#Rf|XOQU>SDRL*akeVhYN&kfp7iVrgCEP5d8ux&Km~@V%G#qCkwG zuS;YI2D-#Bfit~h1f#$>dXz=)9OQj41x!eo4gn|k96+_kBoul;kw68Offa&tz(xq1 zBe(>t5?lnFf6iSAfy>POPrYk|_d3BQa2~h;+$7inz96{e11IJ-aHj)q6Wk+s&?UYl bc;o}hdtJhlkXUG=`+NEm8Wm~`y&wPp2UJh~ literal 0 HcmV?d00001 diff --git a/man/baseline_table.Rd b/man/baseline_table.Rd new file mode 100644 index 0000000..c0a9b4c --- /dev/null +++ b/man/baseline_table.Rd @@ -0,0 +1,32 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/baseline_table.R +\name{baseline_table} +\alias{baseline_table} +\title{Print a flexible baseline characteristics table} +\usage{ +baseline_table( + data, + fun.args = NULL, + fun = gtsummary::tbl_summary, + vars = NULL +) +} +\arguments{ +\item{data}{data set} + +\item{fun.args}{list of arguments passed to} + +\item{fun}{function to} + +\item{vars}{character vector of variables to include} +} +\value{ +object of standard class for fun +} +\description{ +Print a flexible baseline characteristics table +} +\examples{ +mtcars |> baseline_table() +mtcars |> baseline_table(fun.args = list(by = "gear")) +} diff --git a/man/file_extension.Rd b/man/file_extension.Rd new file mode 100644 index 0000000..19c4db7 --- /dev/null +++ b/man/file_extension.Rd @@ -0,0 +1,21 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/helpers.R +\name{file_extension} +\alias{file_extension} +\title{Helper to import files correctly} +\usage{ +file_extension(filenames) +} +\arguments{ +\item{filenames}{file names} +} +\value{ +character vector +} +\description{ +Helper to import files correctly +} +\examples{ +file_extension(list.files(here::here(""))[[2]])[[1]] +file_extension(c("file.cd..ks", "file")) +} diff --git a/man/getfun.Rd b/man/getfun.Rd new file mode 100644 index 0000000..a17a830 --- /dev/null +++ b/man/getfun.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/helpers.R +\name{getfun} +\alias{getfun} +\title{Wrapper function to get function from character vector referring to function from namespace. Passed to 'do.call()'} +\usage{ +getfun(x) +} +\arguments{ +\item{x}{function or function name} +} +\value{ +function or character vector +} +\description{ +This function follows the idea from this comment: https://stackoverflow.com/questions/38983179/do-call-a-function-in-r-without-loading-the-package +} +\examples{ +getfun("stats::lm") +} diff --git a/man/read_input.Rd b/man/read_input.Rd new file mode 100644 index 0000000..020ba8e --- /dev/null +++ b/man/read_input.Rd @@ -0,0 +1,22 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/helpers.R +\name{read_input} +\alias{read_input} +\title{Flexible file import based on extension} +\usage{ +read_input(file, consider.na = c("NA", "\\"\\"", "")) +} +\arguments{ +\item{file}{file name} + +\item{consider.na}{character vector of strings to consider as NAs} +} +\value{ +tibble +} +\description{ +Flexible file import based on extension +} +\examples{ +read_input("https://raw.githubusercontent.com/agdamsbo/cognitive.index.lookup/main/data/sample.csv") +} diff --git a/man/regression_model.Rd b/man/regression_model.Rd new file mode 100644 index 0000000..505cedc --- /dev/null +++ b/man/regression_model.Rd @@ -0,0 +1,54 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/regression_model.R +\name{regression_model} +\alias{regression_model} +\title{Print a flexible baseline characteristics table} +\usage{ +regression_model( + data, + outcome.str = "gear", + outcome.factor = TRUE, + formula.str = NULL, + args.list = list(Hess = TRUE, method = "logistic"), + fun = "MASS::polr", + vars = NULL +) +} +\arguments{ +\item{data}{data set} + +\item{outcome.str}{Name of outcome variable. Character vector.} + +\item{outcome.factor}{Factorize outcome variable. Logical.} + +\item{formula.str}{Formula as string. Passed through 'glue::glue'. If given, 'outcome.str' and 'vars' are ignored. Optional.} + +\item{args.list}{List of arguments passed to 'fun' with 'do.call'.} + +\item{fun}{Name of function as character vector or function to use for model creation.} + +\item{vars}{character vector of variables to include} +} +\value{ +object of standard class for fun +} +\description{ +Print a flexible baseline characteristics table +} +\examples{ +gtsummary::trial |> + regression_model(outcome.str = "stage", fun = "MASS::polr") +gtsummary::trial |> + regression_model( + outcome.str = "age", + outcome.factor = FALSE, + fun = "stats::lm", + formula.str = "{outcome.str}~.", + args.list = NULL + ) +gtsummary::trial |> regression_model( + outcome.str = "trt", + fun = "stats::glm", + args.list = list(family = binomial(link = "logit")) +) +} diff --git a/man/regression_table.Rd b/man/regression_table.Rd new file mode 100644 index 0000000..c7d57f9 --- /dev/null +++ b/man/regression_table.Rd @@ -0,0 +1,45 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/regression_table.R +\name{regression_table} +\alias{regression_table} +\title{Create table of regression model} +\usage{ +regression_table(data, args.list = NULL, fun = "gtsummary::tbl_regression") +} +\arguments{ +\item{data}{regression model} + +\item{args.list}{list of arguments passed to 'fun'.} + +\item{fun}{function to use for table creation. Default is "gtsummary::tbl_regression".} +} +\value{ +object of standard class for fun +} +\description{ +Create table of regression model +} +\examples{ +gtsummary::trial |> + regression_model( + outcome.str = "stage", + fun = "MASS::polr" + ) |> + regression_table(args.list = list(exponentiate = TRUE)) +gtsummary::trial |> + regression_model( + outcome.str = "age", + outcome.factor = FALSE, + fun = "stats::lm", + formula.str = "{outcome.str}~.", + args.list = NULL + ) |> + regression_table() +gtsummary::trial |> + regression_model( + outcome.str = "trt", + fun = "stats::glm", + args.list = list(family = binomial(link = "logit")) + ) |> + regression_table(args.list = list(exponentiate = TRUE)) +} diff --git a/man/write_quarto.Rd b/man/write_quarto.Rd new file mode 100644 index 0000000..7f3e23d --- /dev/null +++ b/man/write_quarto.Rd @@ -0,0 +1,31 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/helpers.R +\name{write_quarto} +\alias{write_quarto} +\title{Wrapper to save data in RDS, load into specified qmd and render} +\usage{ +write_quarto( + data, + fileformat, + qmd.file = here::here("analyses.qmd"), + file = NULL, + ... +) +} +\arguments{ +\item{data}{list to pass to qmd} + +\item{fileformat}{output format. Ignored if file!=NULL} + +\item{qmd.file}{qmd file to render. Default is 'here::here("analyses.qmd")'} + +\item{file}{exact filename (Optional)} + +\item{...}{Ignored for now} +} +\value{ +none +} +\description{ +Wrapper to save data in RDS, load into specified qmd and render +} diff --git a/publish_shiny.R b/publish_shiny.R new file mode 100644 index 0000000..9c6c288 --- /dev/null +++ b/publish_shiny.R @@ -0,0 +1,15 @@ +# Prep for shiny +# system2("cat ./R/index_from_raw.R ./R/plot_index.R ./R/read_file.R > ./R/functions.R") + +project.aid::merge_scripts(list.files("R/",full.names = TRUE),dest = here::here("app/functions.R")) + +# Typical shiny +shiny::runApp(appDir = here::here("app/"), launch.browser = TRUE) + +project.aid::deploy_shiny( + files = c("server.R", "ui.R"), + account.name = "agdamsbo", + name.app = "webResearch", + name.token = "rsconnect_agdamsbo_token", + name.secret = "rsconnect_agdamsbo_secret" +) diff --git a/renv.lock b/renv.lock new file mode 100644 index 0000000..f60e313 --- /dev/null +++ b/renv.lock @@ -0,0 +1,1730 @@ +{ + "R": { + "Version": "4.4.1", + "Repositories": [ + { + "Name": "CRAN", + "URL": "https://cloud.r-project.org" + } + ] + }, + "Packages": { + "PKI": { + "Package": "PKI", + "Version": "0.1-14", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "base64enc" + ], + "Hash": "f5b9c6b2f62f1fa3dd53fd1ddccbb241" + }, + "R6": { + "Package": "R6", + "Version": "2.5.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "470851b6d5d0ac559e9d01bb352b4021" + }, + "RColorBrewer": { + "Package": "RColorBrewer", + "Version": "1.1-3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "45f0398006e83a5b10b72a90663d8d8c" + }, + "Rcpp": { + "Package": "Rcpp", + "Version": "1.0.13-1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "methods", + "utils" + ], + "Hash": "6b868847b365672d6c1677b1608da9ed" + }, + "V8": { + "Package": "V8", + "Version": "6.0.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "Rcpp", + "curl", + "jsonlite", + "utils" + ], + "Hash": "6603bfcbc7883a5fed41fb13042a3899" + }, + "archive": { + "Package": "archive", + "Version": "1.1.9", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "glue", + "rlang", + "tibble" + ], + "Hash": "d26b62e131d4a8b65aba4e9554a4bf74" + }, + "askpass": { + "Package": "askpass", + "Version": "1.2.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "sys" + ], + "Hash": "c39f4155b3ceb1a9a2799d700fbd4b6a" + }, + "assertthat": { + "Package": "assertthat", + "Version": "0.2.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "tools" + ], + "Hash": "50c838a310445e954bc13f26f26a6ecf" + }, + "base64enc": { + "Package": "base64enc", + "Version": "0.1-3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "543776ae6848fde2f48ff3816d0628bc" + }, + "bigD": { + "Package": "bigD", + "Version": "0.2.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "93637e906f3fe962413912c956eb44db" + }, + "bit": { + "Package": "bit", + "Version": "4.5.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "5dc7b2677d65d0e874fc4aaf0e879987" + }, + "bit64": { + "Package": "bit64", + "Version": "4.5.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "bit", + "methods", + "stats", + "utils" + ], + "Hash": "e84984bf5f12a18628d9a02322128dfd" + }, + "bitops": { + "Package": "bitops", + "Version": "1.0-9", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "d972ef991d58c19e6efa71b21f5e144b" + }, + "brio": { + "Package": "brio", + "Version": "1.1.5", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "c1ee497a6d999947c2c224ae46799b1a" + }, + "bslib": { + "Package": "bslib", + "Version": "0.8.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "base64enc", + "cachem", + "fastmap", + "grDevices", + "htmltools", + "jquerylib", + "jsonlite", + "lifecycle", + "memoise", + "mime", + "rlang", + "sass" + ], + "Hash": "b299c6741ca9746fb227debcb0f9fb6c" + }, + "cachem": { + "Package": "cachem", + "Version": "1.1.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "fastmap", + "rlang" + ], + "Hash": "cd9a672193789068eb5a2aad65a0dedf" + }, + "calendar": { + "Package": "calendar", + "Version": "0.2.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "lubridate", + "tibble" + ], + "Hash": "8204ab7185576575d91df30ef48a39b3" + }, + "callr": { + "Package": "callr", + "Version": "3.7.6", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "processx", + "utils" + ], + "Hash": "d7e13f49c19103ece9e58ad2d83a7354" + }, + "cards": { + "Package": "cards", + "Version": "0.3.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "dplyr", + "glue", + "rlang", + "tidyr", + "tidyselect" + ], + "Hash": "2147e8448f4eb87197520fc1710855c7" + }, + "cellranger": { + "Package": "cellranger", + "Version": "1.1.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "rematch", + "tibble" + ], + "Hash": "f61dbaec772ccd2e17705c1e872e9e7c" + }, + "cli": { + "Package": "cli", + "Version": "3.6.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "utils" + ], + "Hash": "b21916dd77a27642b447374a5d30ecf3" + }, + "clipr": { + "Package": "clipr", + "Version": "0.8.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "utils" + ], + "Hash": "3f038e5ac7f41d4ac41ce658c85e3042" + }, + "colorspace": { + "Package": "colorspace", + "Version": "2.1-1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "grDevices", + "graphics", + "methods", + "stats" + ], + "Hash": "d954cb1c57e8d8b756165d7ba18aa55a" + }, + "commonmark": { + "Package": "commonmark", + "Version": "1.9.2", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "14eb0596f987c71535d07c3aff814742" + }, + "cpp11": { + "Package": "cpp11", + "Version": "0.5.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "91570bba75d0c9d3f1040c835cee8fba" + }, + "crayon": { + "Package": "crayon", + "Version": "1.5.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "grDevices", + "methods", + "utils" + ], + "Hash": "859d96e65ef198fd43e82b9628d593ef" + }, + "curl": { + "Package": "curl", + "Version": "6.0.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "ff51697d9205fe715f29e7171e874c6e" + }, + "desc": { + "Package": "desc", + "Version": "1.4.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "cli", + "utils" + ], + "Hash": "99b79fcbd6c4d1ce087f5c5c758b384f" + }, + "digest": { + "Package": "digest", + "Version": "0.6.37", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "utils" + ], + "Hash": "33698c4b3127fc9f506654607fb73676" + }, + "dplyr": { + "Package": "dplyr", + "Version": "1.1.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "cli", + "generics", + "glue", + "lifecycle", + "magrittr", + "methods", + "pillar", + "rlang", + "tibble", + "tidyselect", + "utils", + "vctrs" + ], + "Hash": "fedd9d00c2944ff00a0e2696ccf048ec" + }, + "evaluate": { + "Package": "evaluate", + "Version": "1.0.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "3fd29944b231036ad67c3edb32e02201" + }, + "fansi": { + "Package": "fansi", + "Version": "1.0.6", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "grDevices", + "utils" + ], + "Hash": "962174cf2aeb5b9eea581522286a911f" + }, + "farver": { + "Package": "farver", + "Version": "2.1.2", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "680887028577f3fa2a81e410ed0d6e42" + }, + "fastmap": { + "Package": "fastmap", + "Version": "1.2.0", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "aa5e1cd11c2d15497494c5292d7ffcc8" + }, + "filelock": { + "Package": "filelock", + "Version": "1.0.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "192053c276525c8495ccfd523aa8f2d1" + }, + "fontawesome": { + "Package": "fontawesome", + "Version": "0.5.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "htmltools", + "rlang" + ], + "Hash": "c2efdd5f0bcd1ea861c2d4e2a883a67d" + }, + "forcats": { + "Package": "forcats", + "Version": "1.0.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "glue", + "lifecycle", + "magrittr", + "rlang", + "tibble" + ], + "Hash": "1a0a9a3d5083d0d573c4214576f1e690" + }, + "fs": { + "Package": "fs", + "Version": "1.6.5", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "methods" + ], + "Hash": "7f48af39fa27711ea5fbd183b399920d" + }, + "generics": { + "Package": "generics", + "Version": "0.1.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "methods" + ], + "Hash": "15e9634c0fcd294799e9b2e929ed1b86" + }, + "gh": { + "Package": "gh", + "Version": "1.4.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "gitcreds", + "glue", + "httr2", + "ini", + "jsonlite", + "lifecycle", + "rlang" + ], + "Hash": "fbbbc48eba7a6626a08bb365e44b563b" + }, + "gitcreds": { + "Package": "gitcreds", + "Version": "0.1.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "ab08ac61f3e1be454ae21911eb8bc2fe" + }, + "glue": { + "Package": "glue", + "Version": "1.8.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "methods" + ], + "Hash": "5899f1eaa825580172bb56c08266f37c" + }, + "gt": { + "Package": "gt", + "Version": "0.11.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "base64enc", + "bigD", + "bitops", + "cli", + "commonmark", + "dplyr", + "fs", + "glue", + "htmltools", + "htmlwidgets", + "juicyjuice", + "magrittr", + "markdown", + "reactable", + "rlang", + "sass", + "scales", + "tidyselect", + "vctrs", + "xml2" + ], + "Hash": "3170d1f0f45e531c241179ab57cd30bd" + }, + "gtsummary": { + "Package": "gtsummary", + "Version": "2.0.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cards", + "cli", + "dplyr", + "glue", + "gt", + "lifecycle", + "rlang", + "tidyr", + "vctrs" + ], + "Hash": "cd4d593e8ce0ad4e5c2c0acc50ce7330" + }, + "haven": { + "Package": "haven", + "Version": "2.5.4", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R", + "cli", + "cpp11", + "forcats", + "hms", + "lifecycle", + "methods", + "readr", + "rlang", + "tibble", + "tidyselect", + "vctrs" + ], + "Hash": "9171f898db9d9c4c1b2c745adc2c1ef1" + }, + "here": { + "Package": "here", + "Version": "1.0.1", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "rprojroot" + ], + "Hash": "24b224366f9c2e7534d2344d10d59211" + }, + "highr": { + "Package": "highr", + "Version": "0.11", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "xfun" + ], + "Hash": "d65ba49117ca223614f71b60d85b8ab7" + }, + "hms": { + "Package": "hms", + "Version": "1.1.3", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "lifecycle", + "methods", + "pkgconfig", + "rlang", + "vctrs" + ], + "Hash": "b59377caa7ed00fa41808342002138f9" + }, + "htmltools": { + "Package": "htmltools", + "Version": "0.5.8.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "base64enc", + "digest", + "fastmap", + "grDevices", + "rlang", + "utils" + ], + "Hash": "81d371a9cc60640e74e4ab6ac46dcedc" + }, + "htmlwidgets": { + "Package": "htmlwidgets", + "Version": "1.6.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "grDevices", + "htmltools", + "jsonlite", + "knitr", + "rmarkdown", + "yaml" + ], + "Hash": "04291cc45198225444a397606810ac37" + }, + "httpuv": { + "Package": "httpuv", + "Version": "1.6.15", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "Rcpp", + "later", + "promises", + "utils" + ], + "Hash": "d55aa087c47a63ead0f6fc10f8fa1ee0" + }, + "httr2": { + "Package": "httr2", + "Version": "1.0.6", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "cli", + "curl", + "glue", + "lifecycle", + "magrittr", + "openssl", + "rappdirs", + "rlang", + "vctrs", + "withr" + ], + "Hash": "3ef5d07ec78803475a94367d71b40c41" + }, + "ini": { + "Package": "ini", + "Version": "0.3.1", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "6154ec2223172bce8162d4153cda21f7" + }, + "jquerylib": { + "Package": "jquerylib", + "Version": "0.1.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "htmltools" + ], + "Hash": "5aab57a3bd297eee1c1d862735972182" + }, + "jsonlite": { + "Package": "jsonlite", + "Version": "1.8.9", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "methods" + ], + "Hash": "4e993b65c2c3ffbffce7bb3e2c6f832b" + }, + "juicyjuice": { + "Package": "juicyjuice", + "Version": "0.1.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "V8" + ], + "Hash": "3bcd11943da509341838da9399e18bce" + }, + "keyring": { + "Package": "keyring", + "Version": "1.3.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "askpass", + "assertthat", + "filelock", + "openssl", + "rappdirs", + "sodium", + "tools", + "utils", + "yaml" + ], + "Hash": "5cd8cfb2e90c57110b7dd1785c599aba" + }, + "knitr": { + "Package": "knitr", + "Version": "1.49", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "evaluate", + "highr", + "methods", + "tools", + "xfun", + "yaml" + ], + "Hash": "9fcb189926d93c636dea94fbe4f44480" + }, + "labeling": { + "Package": "labeling", + "Version": "0.4.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "graphics", + "stats" + ], + "Hash": "b64ec208ac5bc1852b285f665d6368b3" + }, + "later": { + "Package": "later", + "Version": "1.3.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "Rcpp", + "rlang" + ], + "Hash": "a3e051d405326b8b0012377434c62b37" + }, + "lifecycle": { + "Package": "lifecycle", + "Version": "1.0.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "glue", + "rlang" + ], + "Hash": "b8552d117e1b808b09a832f589b79035" + }, + "lpSolve": { + "Package": "lpSolve", + "Version": "5.6.21", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "730a90bdc519fb0caff03df11218ddd8" + }, + "lubridate": { + "Package": "lubridate", + "Version": "1.9.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "generics", + "methods", + "timechange" + ], + "Hash": "680ad542fbcf801442c83a6ac5a2126c" + }, + "magrittr": { + "Package": "magrittr", + "Version": "2.0.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "7ce2733a9826b3aeb1775d56fd305472" + }, + "markdown": { + "Package": "markdown", + "Version": "1.13", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "commonmark", + "utils", + "xfun" + ], + "Hash": "074efab766a9d6360865ad39512f2a7e" + }, + "memoise": { + "Package": "memoise", + "Version": "2.0.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "cachem", + "rlang" + ], + "Hash": "e2817ccf4a065c5d9d7f2cfbe7c1d78c" + }, + "mime": { + "Package": "mime", + "Version": "0.12", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "tools" + ], + "Hash": "18e9c28c1d3ca1560ce30658b22ce104" + }, + "minty": { + "Package": "minty", + "Version": "0.0.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cpp11", + "tzdb" + ], + "Hash": "d19909f1b3fac42e7f3ac635321dbb15" + }, + "munsell": { + "Package": "munsell", + "Version": "0.5.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "colorspace", + "methods" + ], + "Hash": "4fd8900853b746af55b81fda99da7695" + }, + "officer": { + "Package": "officer", + "Version": "0.6.7", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R6", + "cli", + "grDevices", + "graphics", + "openssl", + "ragg", + "stats", + "utils", + "uuid", + "xml2", + "zip" + ], + "Hash": "d6c0a4e796301a5d252de42c92a9a8b9" + }, + "openssl": { + "Package": "openssl", + "Version": "2.2.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "askpass" + ], + "Hash": "d413e0fef796c9401a4419485f709ca1" + }, + "openxlsx2": { + "Package": "openxlsx2", + "Version": "1.10", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "Rcpp", + "grDevices", + "magrittr", + "stringi", + "utils", + "zip" + ], + "Hash": "ee4b99fc9ca05bbfd29d567785c093d2" + }, + "packrat": { + "Package": "packrat", + "Version": "0.9.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "tools", + "utils" + ], + "Hash": "55ddd2d4a1959535f18393478b0c14a6" + }, + "pillar": { + "Package": "pillar", + "Version": "1.9.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "cli", + "fansi", + "glue", + "lifecycle", + "rlang", + "utf8", + "utils", + "vctrs" + ], + "Hash": "15da5a8412f317beeee6175fbc76f4bb" + }, + "pkgbuild": { + "Package": "pkgbuild", + "Version": "1.4.5", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "callr", + "cli", + "desc", + "processx" + ], + "Hash": "30eaaab94db72652e72e3475c1b55278" + }, + "pkgcache": { + "Package": "pkgcache", + "Version": "2.2.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "callr", + "cli", + "curl", + "filelock", + "jsonlite", + "processx", + "tools", + "utils" + ], + "Hash": "502554da4ec4d917b737e6b0fe14dd11" + }, + "pkgconfig": { + "Package": "pkgconfig", + "Version": "2.0.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "utils" + ], + "Hash": "01f28d4278f15c76cddbea05899c5d6f" + }, + "pkgdepends": { + "Package": "pkgdepends", + "Version": "0.8.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "callr", + "cli", + "curl", + "desc", + "filelock", + "jsonlite", + "lpSolve", + "pkgbuild", + "pkgcache", + "processx", + "ps", + "stats", + "utils", + "zip" + ], + "Hash": "eb7e3e965327555a527196d26d0643e4" + }, + "prettyunits": { + "Package": "prettyunits", + "Version": "1.2.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "6b01fc98b1e86c4f705ce9dcfd2f57c7" + }, + "processx": { + "Package": "processx", + "Version": "3.8.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "ps", + "utils" + ], + "Hash": "0c90a7d71988856bad2a2a45dd871bb9" + }, + "progress": { + "Package": "progress", + "Version": "1.2.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "crayon", + "hms", + "prettyunits" + ], + "Hash": "f4625e061cb2865f111b47ff163a5ca6" + }, + "project.aid": { + "Package": "project.aid", + "Version": "24.10.1", + "Source": "GitHub", + "RemoteType": "github", + "RemoteHost": "api.github.com", + "RemoteUsername": "agdamsbo", + "RemoteRepo": "project.aid", + "RemoteRef": "main", + "RemoteSha": "1f90bace185f2b3e2eb01e5f8c83ed7cb323725a", + "Requirements": [ + "calendar", + "dplyr", + "glue", + "gt", + "gtsummary", + "haven", + "here", + "httpuv", + "keyring", + "lubridate", + "officer", + "openxlsx2", + "purrr", + "readODS", + "readr", + "renv", + "rsconnect", + "shinylive", + "tidyselect" + ], + "Hash": "2027adcc2eec408bc8c24101a515da76" + }, + "promises": { + "Package": "promises", + "Version": "1.3.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R6", + "Rcpp", + "fastmap", + "later", + "magrittr", + "rlang", + "stats" + ], + "Hash": "434cd5388a3979e74be5c219bcd6e77d" + }, + "ps": { + "Package": "ps", + "Version": "1.8.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "utils" + ], + "Hash": "b4404b1de13758dea1c0484ad0d48563" + }, + "purrr": { + "Package": "purrr", + "Version": "1.0.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "lifecycle", + "magrittr", + "rlang", + "vctrs" + ], + "Hash": "1cba04a4e9414bdefc9dcaa99649a8dc" + }, + "quarto": { + "Package": "quarto", + "Version": "1.4.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "jsonlite", + "later", + "processx", + "rlang", + "rmarkdown", + "rstudioapi", + "tools", + "utils", + "yaml" + ], + "Hash": "af456d7a181750812bd8b2bfedb3ea4e" + }, + "ragg": { + "Package": "ragg", + "Version": "1.3.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "systemfonts", + "textshaping" + ], + "Hash": "0595fe5e47357111f29ad19101c7d271" + }, + "rappdirs": { + "Package": "rappdirs", + "Version": "0.3.3", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "5e3c5dc0b071b21fa128676560dbe94d" + }, + "reactR": { + "Package": "reactR", + "Version": "0.6.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "htmltools" + ], + "Hash": "b8e3d93f508045812f47136c7c44c251" + }, + "reactable": { + "Package": "reactable", + "Version": "0.4.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "digest", + "htmltools", + "htmlwidgets", + "jsonlite", + "reactR" + ], + "Hash": "6069eb2a6597963eae0605c1875ff14c" + }, + "readODS": { + "Package": "readODS", + "Version": "2.3.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cellranger", + "cpp11", + "minty", + "stringi", + "tibble", + "tools", + "vctrs", + "zip" + ], + "Hash": "d81971565325ed8cbe59993ed5c0e611" + }, + "readr": { + "Package": "readr", + "Version": "2.1.5", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "cli", + "clipr", + "cpp11", + "crayon", + "hms", + "lifecycle", + "methods", + "rlang", + "tibble", + "tzdb", + "utils", + "vroom" + ], + "Hash": "9de96463d2117f6ac49980577939dfb3" + }, + "rematch": { + "Package": "rematch", + "Version": "2.0.0", + "Source": "Repository", + "Repository": "RSPM", + "Hash": "cbff1b666c6fa6d21202f07e2318d4f1" + }, + "renv": { + "Package": "renv", + "Version": "1.0.11", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "utils" + ], + "Hash": "47623f66b4e80b3b0587bc5d7b309888" + }, + "rlang": { + "Package": "rlang", + "Version": "1.1.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "utils" + ], + "Hash": "3eec01f8b1dee337674b2e34ab1f9bc1" + }, + "rmarkdown": { + "Package": "rmarkdown", + "Version": "2.29", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "bslib", + "evaluate", + "fontawesome", + "htmltools", + "jquerylib", + "jsonlite", + "knitr", + "methods", + "tinytex", + "tools", + "utils", + "xfun", + "yaml" + ], + "Hash": "df99277f63d01c34e95e3d2f06a79736" + }, + "rprojroot": { + "Package": "rprojroot", + "Version": "2.0.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "4c8415e0ec1e29f3f4f6fc108bef0144" + }, + "rsconnect": { + "Package": "rsconnect", + "Version": "1.3.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "PKI", + "R", + "cli", + "curl", + "digest", + "jsonlite", + "lifecycle", + "openssl", + "packrat", + "renv", + "rlang", + "rstudioapi", + "tools", + "yaml" + ], + "Hash": "5fc91933f6f54be0f870a327c21e1d6a" + }, + "rstudioapi": { + "Package": "rstudioapi", + "Version": "0.17.1", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "5f90cd73946d706cfe26024294236113" + }, + "sass": { + "Package": "sass", + "Version": "0.4.9", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R6", + "fs", + "htmltools", + "rappdirs", + "rlang" + ], + "Hash": "d53dbfddf695303ea4ad66f86e99b95d" + }, + "scales": { + "Package": "scales", + "Version": "1.3.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "RColorBrewer", + "cli", + "farver", + "glue", + "labeling", + "lifecycle", + "munsell", + "rlang", + "viridisLite" + ], + "Hash": "c19df082ba346b0ffa6f833e92de34d1" + }, + "shiny": { + "Package": "shiny", + "Version": "1.9.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "R6", + "bslib", + "cachem", + "commonmark", + "crayon", + "fastmap", + "fontawesome", + "glue", + "grDevices", + "htmltools", + "httpuv", + "jsonlite", + "later", + "lifecycle", + "methods", + "mime", + "promises", + "rlang", + "sourcetools", + "tools", + "utils", + "withr", + "xtable" + ], + "Hash": "6a293995a66e12c48d13aa1f957d09c7" + }, + "shinylive": { + "Package": "shinylive", + "Version": "0.2.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "archive", + "brio", + "cli", + "fs", + "gh", + "glue", + "httr2", + "jsonlite", + "pkgdepends", + "progress", + "rappdirs", + "renv", + "rlang", + "tools", + "whisker", + "withr" + ], + "Hash": "224c8c0502bb0ead1fd1b4b32ea04a90" + }, + "sodium": { + "Package": "sodium", + "Version": "1.3.2", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "869b09ca565ecaa9efc62534ebfa3efd" + }, + "sourcetools": { + "Package": "sourcetools", + "Version": "0.1.7-1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "5f5a7629f956619d519205ec475fe647" + }, + "stringi": { + "Package": "stringi", + "Version": "1.8.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "stats", + "tools", + "utils" + ], + "Hash": "39e1144fd75428983dc3f63aa53dfa91" + }, + "stringr": { + "Package": "stringr", + "Version": "1.5.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "glue", + "lifecycle", + "magrittr", + "rlang", + "stringi", + "vctrs" + ], + "Hash": "960e2ae9e09656611e0b8214ad543207" + }, + "sys": { + "Package": "sys", + "Version": "3.4.3", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "de342ebfebdbf40477d0758d05426646" + }, + "systemfonts": { + "Package": "systemfonts", + "Version": "1.1.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cpp11", + "lifecycle" + ], + "Hash": "213b6b8ed5afbf934843e6c3b090d418" + }, + "textshaping": { + "Package": "textshaping", + "Version": "0.4.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cpp11", + "lifecycle", + "systemfonts" + ], + "Hash": "5142f8bc78ed3d819d26461b641627ce" + }, + "tibble": { + "Package": "tibble", + "Version": "3.2.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "fansi", + "lifecycle", + "magrittr", + "methods", + "pillar", + "pkgconfig", + "rlang", + "utils", + "vctrs" + ], + "Hash": "a84e2cc86d07289b3b6f5069df7a004c" + }, + "tidyr": { + "Package": "tidyr", + "Version": "1.3.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "cpp11", + "dplyr", + "glue", + "lifecycle", + "magrittr", + "purrr", + "rlang", + "stringr", + "tibble", + "tidyselect", + "utils", + "vctrs" + ], + "Hash": "915fb7ce036c22a6a33b5a8adb712eb1" + }, + "tidyselect": { + "Package": "tidyselect", + "Version": "1.2.1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "glue", + "lifecycle", + "rlang", + "vctrs", + "withr" + ], + "Hash": "829f27b9c4919c16b593794a6344d6c0" + }, + "timechange": { + "Package": "timechange", + "Version": "0.3.0", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cpp11" + ], + "Hash": "c5f3c201b931cd6474d17d8700ccb1c8" + }, + "tinytex": { + "Package": "tinytex", + "Version": "0.54", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "xfun" + ], + "Hash": "3ec7e3ddcacc2d34a9046941222bf94d" + }, + "tzdb": { + "Package": "tzdb", + "Version": "0.4.0", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R", + "cpp11" + ], + "Hash": "f561504ec2897f4d46f0c7657e488ae1" + }, + "utf8": { + "Package": "utf8", + "Version": "1.2.4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "62b65c52671e6665f803ff02954446e9" + }, + "uuid": { + "Package": "uuid", + "Version": "1.2-1", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "34e965e62a41fcafb1ca60e9b142085b" + }, + "vctrs": { + "Package": "vctrs", + "Version": "0.6.5", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "glue", + "lifecycle", + "rlang" + ], + "Hash": "c03fa420630029418f7e6da3667aac4a" + }, + "viridisLite": { + "Package": "viridisLite", + "Version": "0.4.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R" + ], + "Hash": "c826c7c4241b6fc89ff55aaea3fa7491" + }, + "vroom": { + "Package": "vroom", + "Version": "1.6.5", + "Source": "Repository", + "Repository": "RSPM", + "Requirements": [ + "R", + "bit64", + "cli", + "cpp11", + "crayon", + "glue", + "hms", + "lifecycle", + "methods", + "progress", + "rlang", + "stats", + "tibble", + "tidyselect", + "tzdb", + "vctrs", + "withr" + ], + "Hash": "390f9315bc0025be03012054103d227c" + }, + "whisker": { + "Package": "whisker", + "Version": "0.4.1", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "c6abfa47a46d281a7d5159d0a8891e88" + }, + "withr": { + "Package": "withr", + "Version": "3.0.2", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "grDevices", + "graphics" + ], + "Hash": "cc2d62c76458d425210d1eb1478b30b4" + }, + "xfun": { + "Package": "xfun", + "Version": "0.49", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "grDevices", + "stats", + "tools" + ], + "Hash": "8687398773806cfff9401a2feca96298" + }, + "xml2": { + "Package": "xml2", + "Version": "1.3.6", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "cli", + "methods", + "rlang" + ], + "Hash": "1d0336142f4cd25d8d23cd3ba7a8fb61" + }, + "xtable": { + "Package": "xtable", + "Version": "1.8-4", + "Source": "Repository", + "Repository": "CRAN", + "Requirements": [ + "R", + "stats", + "utils" + ], + "Hash": "b8acdf8af494d9ec19ccb2481a9b11c2" + }, + "yaml": { + "Package": "yaml", + "Version": "2.3.10", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "51dab85c6c98e50a18d7551e9d49f76c" + }, + "zip": { + "Package": "zip", + "Version": "2.3.1", + "Source": "Repository", + "Repository": "CRAN", + "Hash": "fcc4bd8e6da2d2011eb64a5e5cc685ab" + } + } +} diff --git a/renv/.gitignore b/renv/.gitignore new file mode 100644 index 0000000..0ec0cbb --- /dev/null +++ b/renv/.gitignore @@ -0,0 +1,7 @@ +library/ +local/ +cellar/ +lock/ +python/ +sandbox/ +staging/ diff --git a/renv/activate.R b/renv/activate.R new file mode 100644 index 0000000..0eb5108 --- /dev/null +++ b/renv/activate.R @@ -0,0 +1,1305 @@ + +local({ + + # the requested version of renv + version <- "1.0.11" + attr(version, "sha") <- NULL + + # the project directory + project <- Sys.getenv("RENV_PROJECT") + if (!nzchar(project)) + project <- getwd() + + # use start-up diagnostics if enabled + diagnostics <- Sys.getenv("RENV_STARTUP_DIAGNOSTICS", unset = "FALSE") + if (diagnostics) { + start <- Sys.time() + profile <- tempfile("renv-startup-", fileext = ".Rprof") + utils::Rprof(profile) + on.exit({ + utils::Rprof(NULL) + elapsed <- signif(difftime(Sys.time(), start, units = "auto"), digits = 2L) + writeLines(sprintf("- renv took %s to run the autoloader.", format(elapsed))) + writeLines(sprintf("- Profile: %s", profile)) + print(utils::summaryRprof(profile)) + }, add = TRUE) + } + + # figure out whether the autoloader is enabled + enabled <- local({ + + # first, check config option + override <- getOption("renv.config.autoloader.enabled") + if (!is.null(override)) + return(override) + + # if we're being run in a context where R_LIBS is already set, + # don't load -- presumably we're being run as a sub-process and + # the parent process has already set up library paths for us + rcmd <- Sys.getenv("R_CMD", unset = NA) + rlibs <- Sys.getenv("R_LIBS", unset = NA) + if (!is.na(rlibs) && !is.na(rcmd)) + return(FALSE) + + # next, check environment variables + # TODO: prefer using the configuration one in the future + envvars <- c( + "RENV_CONFIG_AUTOLOADER_ENABLED", + "RENV_AUTOLOADER_ENABLED", + "RENV_ACTIVATE_PROJECT" + ) + + for (envvar in envvars) { + envval <- Sys.getenv(envvar, unset = NA) + if (!is.na(envval)) + return(tolower(envval) %in% c("true", "t", "1")) + } + + # enable by default + TRUE + + }) + + # bail if we're not enabled + if (!enabled) { + + # if we're not enabled, we might still need to manually load + # the user profile here + profile <- Sys.getenv("R_PROFILE_USER", unset = "~/.Rprofile") + if (file.exists(profile)) { + cfg <- Sys.getenv("RENV_CONFIG_USER_PROFILE", unset = "TRUE") + if (tolower(cfg) %in% c("true", "t", "1")) + sys.source(profile, envir = globalenv()) + } + + return(FALSE) + + } + + # avoid recursion + if (identical(getOption("renv.autoloader.running"), TRUE)) { + warning("ignoring recursive attempt to run renv autoloader") + return(invisible(TRUE)) + } + + # signal that we're loading renv during R startup + options(renv.autoloader.running = TRUE) + on.exit(options(renv.autoloader.running = NULL), add = TRUE) + + # signal that we've consented to use renv + options(renv.consent = TRUE) + + # load the 'utils' package eagerly -- this ensures that renv shims, which + # mask 'utils' packages, will come first on the search path + library(utils, lib.loc = .Library) + + # unload renv if it's already been loaded + if ("renv" %in% loadedNamespaces()) + unloadNamespace("renv") + + # load bootstrap tools + ansify <- function(text) { + if (renv_ansify_enabled()) + renv_ansify_enhanced(text) + else + renv_ansify_default(text) + } + + renv_ansify_enabled <- function() { + + override <- Sys.getenv("RENV_ANSIFY_ENABLED", unset = NA) + if (!is.na(override)) + return(as.logical(override)) + + pane <- Sys.getenv("RSTUDIO_CHILD_PROCESS_PANE", unset = NA) + if (identical(pane, "build")) + return(FALSE) + + testthat <- Sys.getenv("TESTTHAT", unset = "false") + if (tolower(testthat) %in% "true") + return(FALSE) + + iderun <- Sys.getenv("R_CLI_HAS_HYPERLINK_IDE_RUN", unset = "false") + if (tolower(iderun) %in% "false") + return(FALSE) + + TRUE + + } + + renv_ansify_default <- function(text) { + text + } + + renv_ansify_enhanced <- function(text) { + + # R help links + pattern <- "`\\?(renv::(?:[^`])+)`" + replacement <- "`\033]8;;ide:help:\\1\a?\\1\033]8;;\a`" + text <- gsub(pattern, replacement, text, perl = TRUE) + + # runnable code + pattern <- "`(renv::(?:[^`])+)`" + replacement <- "`\033]8;;ide:run:\\1\a\\1\033]8;;\a`" + text <- gsub(pattern, replacement, text, perl = TRUE) + + # return ansified text + text + + } + + renv_ansify_init <- function() { + + envir <- renv_envir_self() + if (renv_ansify_enabled()) + assign("ansify", renv_ansify_enhanced, envir = envir) + else + assign("ansify", renv_ansify_default, envir = envir) + + } + + `%||%` <- function(x, y) { + if (is.null(x)) y else x + } + + catf <- function(fmt, ..., appendLF = TRUE) { + + quiet <- getOption("renv.bootstrap.quiet", default = FALSE) + if (quiet) + return(invisible()) + + msg <- sprintf(fmt, ...) + cat(msg, file = stdout(), sep = if (appendLF) "\n" else "") + + invisible(msg) + + } + + header <- function(label, + ..., + prefix = "#", + suffix = "-", + n = min(getOption("width"), 78)) + { + label <- sprintf(label, ...) + n <- max(n - nchar(label) - nchar(prefix) - 2L, 8L) + if (n <= 0) + return(paste(prefix, label)) + + tail <- paste(rep.int(suffix, n), collapse = "") + paste0(prefix, " ", label, " ", tail) + + } + + heredoc <- function(text, leave = 0) { + + # remove leading, trailing whitespace + trimmed <- gsub("^\\s*\\n|\\n\\s*$", "", text) + + # split into lines + lines <- strsplit(trimmed, "\n", fixed = TRUE)[[1L]] + + # compute common indent + indent <- regexpr("[^[:space:]]", lines) + common <- min(setdiff(indent, -1L)) - leave + text <- paste(substring(lines, common), collapse = "\n") + + # substitute in ANSI links for executable renv code + ansify(text) + + } + + startswith <- function(string, prefix) { + substring(string, 1, nchar(prefix)) == prefix + } + + bootstrap <- function(version, library) { + + friendly <- renv_bootstrap_version_friendly(version) + section <- header(sprintf("Bootstrapping renv %s", friendly)) + catf(section) + + # attempt to download renv + catf("- Downloading renv ... ", appendLF = FALSE) + withCallingHandlers( + tarball <- renv_bootstrap_download(version), + error = function(err) { + catf("FAILED") + stop("failed to download:\n", conditionMessage(err)) + } + ) + catf("OK") + on.exit(unlink(tarball), add = TRUE) + + # now attempt to install + catf("- Installing renv ... ", appendLF = FALSE) + withCallingHandlers( + status <- renv_bootstrap_install(version, tarball, library), + error = function(err) { + catf("FAILED") + stop("failed to install:\n", conditionMessage(err)) + } + ) + catf("OK") + + # add empty line to break up bootstrapping from normal output + catf("") + + return(invisible()) + } + + renv_bootstrap_tests_running <- function() { + getOption("renv.tests.running", default = FALSE) + } + + renv_bootstrap_repos <- function() { + + # get CRAN repository + cran <- getOption("renv.repos.cran", "https://cloud.r-project.org") + + # check for repos override + repos <- Sys.getenv("RENV_CONFIG_REPOS_OVERRIDE", unset = NA) + if (!is.na(repos)) { + + # check for RSPM; if set, use a fallback repository for renv + rspm <- Sys.getenv("RSPM", unset = NA) + if (identical(rspm, repos)) + repos <- c(RSPM = rspm, CRAN = cran) + + return(repos) + + } + + # check for lockfile repositories + repos <- tryCatch(renv_bootstrap_repos_lockfile(), error = identity) + if (!inherits(repos, "error") && length(repos)) + return(repos) + + # retrieve current repos + repos <- getOption("repos") + + # ensure @CRAN@ entries are resolved + repos[repos == "@CRAN@"] <- cran + + # add in renv.bootstrap.repos if set + default <- c(FALLBACK = "https://cloud.r-project.org") + extra <- getOption("renv.bootstrap.repos", default = default) + repos <- c(repos, extra) + + # remove duplicates that might've snuck in + dupes <- duplicated(repos) | duplicated(names(repos)) + repos[!dupes] + + } + + renv_bootstrap_repos_lockfile <- function() { + + lockpath <- Sys.getenv("RENV_PATHS_LOCKFILE", unset = "renv.lock") + if (!file.exists(lockpath)) + return(NULL) + + lockfile <- tryCatch(renv_json_read(lockpath), error = identity) + if (inherits(lockfile, "error")) { + warning(lockfile) + return(NULL) + } + + repos <- lockfile$R$Repositories + if (length(repos) == 0) + return(NULL) + + keys <- vapply(repos, `[[`, "Name", FUN.VALUE = character(1)) + vals <- vapply(repos, `[[`, "URL", FUN.VALUE = character(1)) + names(vals) <- keys + + return(vals) + + } + + renv_bootstrap_download <- function(version) { + + sha <- attr(version, "sha", exact = TRUE) + + methods <- if (!is.null(sha)) { + + # attempting to bootstrap a development version of renv + c( + function() renv_bootstrap_download_tarball(sha), + function() renv_bootstrap_download_github(sha) + ) + + } else { + + # attempting to bootstrap a release version of renv + c( + function() renv_bootstrap_download_tarball(version), + function() renv_bootstrap_download_cran_latest(version), + function() renv_bootstrap_download_cran_archive(version) + ) + + } + + for (method in methods) { + path <- tryCatch(method(), error = identity) + if (is.character(path) && file.exists(path)) + return(path) + } + + stop("All download methods failed") + + } + + renv_bootstrap_download_impl <- function(url, destfile) { + + mode <- "wb" + + # https://bugs.r-project.org/bugzilla/show_bug.cgi?id=17715 + fixup <- + Sys.info()[["sysname"]] == "Windows" && + substring(url, 1L, 5L) == "file:" + + if (fixup) + mode <- "w+b" + + args <- list( + url = url, + destfile = destfile, + mode = mode, + quiet = TRUE + ) + + if ("headers" %in% names(formals(utils::download.file))) { + headers <- renv_bootstrap_download_custom_headers(url) + if (length(headers) && is.character(headers)) + args$headers <- headers + } + + do.call(utils::download.file, args) + + } + + renv_bootstrap_download_custom_headers <- function(url) { + + headers <- getOption("renv.download.headers") + if (is.null(headers)) + return(character()) + + if (!is.function(headers)) + stopf("'renv.download.headers' is not a function") + + headers <- headers(url) + if (length(headers) == 0L) + return(character()) + + if (is.list(headers)) + headers <- unlist(headers, recursive = FALSE, use.names = TRUE) + + ok <- + is.character(headers) && + is.character(names(headers)) && + all(nzchar(names(headers))) + + if (!ok) + stop("invocation of 'renv.download.headers' did not return a named character vector") + + headers + + } + + renv_bootstrap_download_cran_latest <- function(version) { + + spec <- renv_bootstrap_download_cran_latest_find(version) + type <- spec$type + repos <- spec$repos + + baseurl <- utils::contrib.url(repos = repos, type = type) + ext <- if (identical(type, "source")) + ".tar.gz" + else if (Sys.info()[["sysname"]] == "Windows") + ".zip" + else + ".tgz" + name <- sprintf("renv_%s%s", version, ext) + url <- paste(baseurl, name, sep = "/") + + destfile <- file.path(tempdir(), name) + status <- tryCatch( + renv_bootstrap_download_impl(url, destfile), + condition = identity + ) + + if (inherits(status, "condition")) + return(FALSE) + + # report success and return + destfile + + } + + renv_bootstrap_download_cran_latest_find <- function(version) { + + # check whether binaries are supported on this system + binary <- + getOption("renv.bootstrap.binary", default = TRUE) && + !identical(.Platform$pkgType, "source") && + !identical(getOption("pkgType"), "source") && + Sys.info()[["sysname"]] %in% c("Darwin", "Windows") + + types <- c(if (binary) "binary", "source") + + # iterate over types + repositories + for (type in types) { + for (repos in renv_bootstrap_repos()) { + + # build arguments for utils::available.packages() call + args <- list(type = type, repos = repos) + + # add custom headers if available -- note that + # utils::available.packages() will pass this to download.file() + if ("headers" %in% names(formals(utils::download.file))) { + headers <- renv_bootstrap_download_custom_headers(repos) + if (length(headers) && is.character(headers)) + args$headers <- headers + } + + # retrieve package database + db <- tryCatch( + as.data.frame( + do.call(utils::available.packages, args), + stringsAsFactors = FALSE + ), + error = identity + ) + + if (inherits(db, "error")) + next + + # check for compatible entry + entry <- db[db$Package %in% "renv" & db$Version %in% version, ] + if (nrow(entry) == 0) + next + + # found it; return spec to caller + spec <- list(entry = entry, type = type, repos = repos) + return(spec) + + } + } + + # if we got here, we failed to find renv + fmt <- "renv %s is not available from your declared package repositories" + stop(sprintf(fmt, version)) + + } + + renv_bootstrap_download_cran_archive <- function(version) { + + name <- sprintf("renv_%s.tar.gz", version) + repos <- renv_bootstrap_repos() + urls <- file.path(repos, "src/contrib/Archive/renv", name) + destfile <- file.path(tempdir(), name) + + for (url in urls) { + + status <- tryCatch( + renv_bootstrap_download_impl(url, destfile), + condition = identity + ) + + if (identical(status, 0L)) + return(destfile) + + } + + return(FALSE) + + } + + renv_bootstrap_download_tarball <- function(version) { + + # if the user has provided the path to a tarball via + # an environment variable, then use it + tarball <- Sys.getenv("RENV_BOOTSTRAP_TARBALL", unset = NA) + if (is.na(tarball)) + return() + + # allow directories + if (dir.exists(tarball)) { + name <- sprintf("renv_%s.tar.gz", version) + tarball <- file.path(tarball, name) + } + + # bail if it doesn't exist + if (!file.exists(tarball)) { + + # let the user know we weren't able to honour their request + fmt <- "- RENV_BOOTSTRAP_TARBALL is set (%s) but does not exist." + msg <- sprintf(fmt, tarball) + warning(msg) + + # bail + return() + + } + + catf("- Using local tarball '%s'.", tarball) + tarball + + } + + renv_bootstrap_github_token <- function() { + for (envvar in c("GITHUB_TOKEN", "GITHUB_PAT", "GH_TOKEN")) { + envval <- Sys.getenv(envvar, unset = NA) + if (!is.na(envval)) + return(envval) + } + } + + renv_bootstrap_download_github <- function(version) { + + enabled <- Sys.getenv("RENV_BOOTSTRAP_FROM_GITHUB", unset = "TRUE") + if (!identical(enabled, "TRUE")) + return(FALSE) + + # prepare download options + token <- renv_bootstrap_github_token() + if (nzchar(Sys.which("curl")) && nzchar(token)) { + fmt <- "--location --fail --header \"Authorization: token %s\"" + extra <- sprintf(fmt, token) + saved <- options("download.file.method", "download.file.extra") + options(download.file.method = "curl", download.file.extra = extra) + on.exit(do.call(base::options, saved), add = TRUE) + } else if (nzchar(Sys.which("wget")) && nzchar(token)) { + fmt <- "--header=\"Authorization: token %s\"" + extra <- sprintf(fmt, token) + saved <- options("download.file.method", "download.file.extra") + options(download.file.method = "wget", download.file.extra = extra) + on.exit(do.call(base::options, saved), add = TRUE) + } + + url <- file.path("https://api.github.com/repos/rstudio/renv/tarball", version) + name <- sprintf("renv_%s.tar.gz", version) + destfile <- file.path(tempdir(), name) + + status <- tryCatch( + renv_bootstrap_download_impl(url, destfile), + condition = identity + ) + + if (!identical(status, 0L)) + return(FALSE) + + renv_bootstrap_download_augment(destfile) + + return(destfile) + + } + + # Add Sha to DESCRIPTION. This is stop gap until #890, after which we + # can use renv::install() to fully capture metadata. + renv_bootstrap_download_augment <- function(destfile) { + sha <- renv_bootstrap_git_extract_sha1_tar(destfile) + if (is.null(sha)) { + return() + } + + # Untar + tempdir <- tempfile("renv-github-") + on.exit(unlink(tempdir, recursive = TRUE), add = TRUE) + untar(destfile, exdir = tempdir) + pkgdir <- dir(tempdir, full.names = TRUE)[[1]] + + # Modify description + desc_path <- file.path(pkgdir, "DESCRIPTION") + desc_lines <- readLines(desc_path) + remotes_fields <- c( + "RemoteType: github", + "RemoteHost: api.github.com", + "RemoteRepo: renv", + "RemoteUsername: rstudio", + "RemotePkgRef: rstudio/renv", + paste("RemoteRef: ", sha), + paste("RemoteSha: ", sha) + ) + writeLines(c(desc_lines[desc_lines != ""], remotes_fields), con = desc_path) + + # Re-tar + local({ + old <- setwd(tempdir) + on.exit(setwd(old), add = TRUE) + + tar(destfile, compression = "gzip") + }) + invisible() + } + + # Extract the commit hash from a git archive. Git archives include the SHA1 + # hash as the comment field of the tarball pax extended header + # (see https://www.kernel.org/pub/software/scm/git/docs/git-archive.html) + # For GitHub archives this should be the first header after the default one + # (512 byte) header. + renv_bootstrap_git_extract_sha1_tar <- function(bundle) { + + # open the bundle for reading + # We use gzcon for everything because (from ?gzcon) + # > Reading from a connection which does not supply a 'gzip' magic + # > header is equivalent to reading from the original connection + conn <- gzcon(file(bundle, open = "rb", raw = TRUE)) + on.exit(close(conn)) + + # The default pax header is 512 bytes long and the first pax extended header + # with the comment should be 51 bytes long + # `52 comment=` (11 chars) + 40 byte SHA1 hash + len <- 0x200 + 0x33 + res <- rawToChar(readBin(conn, "raw", n = len)[0x201:len]) + + if (grepl("^52 comment=", res)) { + sub("52 comment=", "", res) + } else { + NULL + } + } + + renv_bootstrap_install <- function(version, tarball, library) { + + # attempt to install it into project library + dir.create(library, showWarnings = FALSE, recursive = TRUE) + output <- renv_bootstrap_install_impl(library, tarball) + + # check for successful install + status <- attr(output, "status") + if (is.null(status) || identical(status, 0L)) + return(status) + + # an error occurred; report it + header <- "installation of renv failed" + lines <- paste(rep.int("=", nchar(header)), collapse = "") + text <- paste(c(header, lines, output), collapse = "\n") + stop(text) + + } + + renv_bootstrap_install_impl <- function(library, tarball) { + + # invoke using system2 so we can capture and report output + bin <- R.home("bin") + exe <- if (Sys.info()[["sysname"]] == "Windows") "R.exe" else "R" + R <- file.path(bin, exe) + + args <- c( + "--vanilla", "CMD", "INSTALL", "--no-multiarch", + "-l", shQuote(path.expand(library)), + shQuote(path.expand(tarball)) + ) + + system2(R, args, stdout = TRUE, stderr = TRUE) + + } + + renv_bootstrap_platform_prefix <- function() { + + # construct version prefix + version <- paste(R.version$major, R.version$minor, sep = ".") + prefix <- paste("R", numeric_version(version)[1, 1:2], sep = "-") + + # include SVN revision for development versions of R + # (to avoid sharing platform-specific artefacts with released versions of R) + devel <- + identical(R.version[["status"]], "Under development (unstable)") || + identical(R.version[["nickname"]], "Unsuffered Consequences") + + if (devel) + prefix <- paste(prefix, R.version[["svn rev"]], sep = "-r") + + # build list of path components + components <- c(prefix, R.version$platform) + + # include prefix if provided by user + prefix <- renv_bootstrap_platform_prefix_impl() + if (!is.na(prefix) && nzchar(prefix)) + components <- c(prefix, components) + + # build prefix + paste(components, collapse = "/") + + } + + renv_bootstrap_platform_prefix_impl <- function() { + + # if an explicit prefix has been supplied, use it + prefix <- Sys.getenv("RENV_PATHS_PREFIX", unset = NA) + if (!is.na(prefix)) + return(prefix) + + # if the user has requested an automatic prefix, generate it + auto <- Sys.getenv("RENV_PATHS_PREFIX_AUTO", unset = NA) + if (is.na(auto) && getRversion() >= "4.4.0") + auto <- "TRUE" + + if (auto %in% c("TRUE", "True", "true", "1")) + return(renv_bootstrap_platform_prefix_auto()) + + # empty string on failure + "" + + } + + renv_bootstrap_platform_prefix_auto <- function() { + + prefix <- tryCatch(renv_bootstrap_platform_os(), error = identity) + if (inherits(prefix, "error") || prefix %in% "unknown") { + + msg <- paste( + "failed to infer current operating system", + "please file a bug report at https://github.com/rstudio/renv/issues", + sep = "; " + ) + + warning(msg) + + } + + prefix + + } + + renv_bootstrap_platform_os <- function() { + + sysinfo <- Sys.info() + sysname <- sysinfo[["sysname"]] + + # handle Windows + macOS up front + if (sysname == "Windows") + return("windows") + else if (sysname == "Darwin") + return("macos") + + # check for os-release files + for (file in c("/etc/os-release", "/usr/lib/os-release")) + if (file.exists(file)) + return(renv_bootstrap_platform_os_via_os_release(file, sysinfo)) + + # check for redhat-release files + if (file.exists("/etc/redhat-release")) + return(renv_bootstrap_platform_os_via_redhat_release()) + + "unknown" + + } + + renv_bootstrap_platform_os_via_os_release <- function(file, sysinfo) { + + # read /etc/os-release + release <- utils::read.table( + file = file, + sep = "=", + quote = c("\"", "'"), + col.names = c("Key", "Value"), + comment.char = "#", + stringsAsFactors = FALSE + ) + + vars <- as.list(release$Value) + names(vars) <- release$Key + + # get os name + os <- tolower(sysinfo[["sysname"]]) + + # read id + id <- "unknown" + for (field in c("ID", "ID_LIKE")) { + if (field %in% names(vars) && nzchar(vars[[field]])) { + id <- vars[[field]] + break + } + } + + # read version + version <- "unknown" + for (field in c("UBUNTU_CODENAME", "VERSION_CODENAME", "VERSION_ID", "BUILD_ID")) { + if (field %in% names(vars) && nzchar(vars[[field]])) { + version <- vars[[field]] + break + } + } + + # join together + paste(c(os, id, version), collapse = "-") + + } + + renv_bootstrap_platform_os_via_redhat_release <- function() { + + # read /etc/redhat-release + contents <- readLines("/etc/redhat-release", warn = FALSE) + + # infer id + id <- if (grepl("centos", contents, ignore.case = TRUE)) + "centos" + else if (grepl("redhat", contents, ignore.case = TRUE)) + "redhat" + else + "unknown" + + # try to find a version component (very hacky) + version <- "unknown" + + parts <- strsplit(contents, "[[:space:]]")[[1L]] + for (part in parts) { + + nv <- tryCatch(numeric_version(part), error = identity) + if (inherits(nv, "error")) + next + + version <- nv[1, 1] + break + + } + + paste(c("linux", id, version), collapse = "-") + + } + + renv_bootstrap_library_root_name <- function(project) { + + # use project name as-is if requested + asis <- Sys.getenv("RENV_PATHS_LIBRARY_ROOT_ASIS", unset = "FALSE") + if (asis) + return(basename(project)) + + # otherwise, disambiguate based on project's path + id <- substring(renv_bootstrap_hash_text(project), 1L, 8L) + paste(basename(project), id, sep = "-") + + } + + renv_bootstrap_library_root <- function(project) { + + prefix <- renv_bootstrap_profile_prefix() + + path <- Sys.getenv("RENV_PATHS_LIBRARY", unset = NA) + if (!is.na(path)) + return(paste(c(path, prefix), collapse = "/")) + + path <- renv_bootstrap_library_root_impl(project) + if (!is.null(path)) { + name <- renv_bootstrap_library_root_name(project) + return(paste(c(path, prefix, name), collapse = "/")) + } + + renv_bootstrap_paths_renv("library", project = project) + + } + + renv_bootstrap_library_root_impl <- function(project) { + + root <- Sys.getenv("RENV_PATHS_LIBRARY_ROOT", unset = NA) + if (!is.na(root)) + return(root) + + type <- renv_bootstrap_project_type(project) + if (identical(type, "package")) { + userdir <- renv_bootstrap_user_dir() + return(file.path(userdir, "library")) + } + + } + + renv_bootstrap_validate_version <- function(version, description = NULL) { + + # resolve description file + # + # avoid passing lib.loc to `packageDescription()` below, since R will + # use the loaded version of the package by default anyhow. note that + # this function should only be called after 'renv' is loaded + # https://github.com/rstudio/renv/issues/1625 + description <- description %||% packageDescription("renv") + + # check whether requested version 'version' matches loaded version of renv + sha <- attr(version, "sha", exact = TRUE) + valid <- if (!is.null(sha)) + renv_bootstrap_validate_version_dev(sha, description) + else + renv_bootstrap_validate_version_release(version, description) + + if (valid) + return(TRUE) + + # the loaded version of renv doesn't match the requested version; + # give the user instructions on how to proceed + dev <- identical(description[["RemoteType"]], "github") + remote <- if (dev) + paste("rstudio/renv", description[["RemoteSha"]], sep = "@") + else + paste("renv", description[["Version"]], sep = "@") + + # display both loaded version + sha if available + friendly <- renv_bootstrap_version_friendly( + version = description[["Version"]], + sha = if (dev) description[["RemoteSha"]] + ) + + fmt <- heredoc(" + renv %1$s was loaded from project library, but this project is configured to use renv %2$s. + - Use `renv::record(\"%3$s\")` to record renv %1$s in the lockfile. + - Use `renv::restore(packages = \"renv\")` to install renv %2$s into the project library. + ") + catf(fmt, friendly, renv_bootstrap_version_friendly(version), remote) + + FALSE + + } + + renv_bootstrap_validate_version_dev <- function(version, description) { + expected <- description[["RemoteSha"]] + is.character(expected) && startswith(expected, version) + } + + renv_bootstrap_validate_version_release <- function(version, description) { + expected <- description[["Version"]] + is.character(expected) && identical(expected, version) + } + + renv_bootstrap_hash_text <- function(text) { + + hashfile <- tempfile("renv-hash-") + on.exit(unlink(hashfile), add = TRUE) + + writeLines(text, con = hashfile) + tools::md5sum(hashfile) + + } + + renv_bootstrap_load <- function(project, libpath, version) { + + # try to load renv from the project library + if (!requireNamespace("renv", lib.loc = libpath, quietly = TRUE)) + return(FALSE) + + # warn if the version of renv loaded does not match + renv_bootstrap_validate_version(version) + + # execute renv load hooks, if any + hooks <- getHook("renv::autoload") + for (hook in hooks) + if (is.function(hook)) + tryCatch(hook(), error = warnify) + + # load the project + renv::load(project) + + TRUE + + } + + renv_bootstrap_profile_load <- function(project) { + + # if RENV_PROFILE is already set, just use that + profile <- Sys.getenv("RENV_PROFILE", unset = NA) + if (!is.na(profile) && nzchar(profile)) + return(profile) + + # check for a profile file (nothing to do if it doesn't exist) + path <- renv_bootstrap_paths_renv("profile", profile = FALSE, project = project) + if (!file.exists(path)) + return(NULL) + + # read the profile, and set it if it exists + contents <- readLines(path, warn = FALSE) + if (length(contents) == 0L) + return(NULL) + + # set RENV_PROFILE + profile <- contents[[1L]] + if (!profile %in% c("", "default")) + Sys.setenv(RENV_PROFILE = profile) + + profile + + } + + renv_bootstrap_profile_prefix <- function() { + profile <- renv_bootstrap_profile_get() + if (!is.null(profile)) + return(file.path("profiles", profile, "renv")) + } + + renv_bootstrap_profile_get <- function() { + profile <- Sys.getenv("RENV_PROFILE", unset = "") + renv_bootstrap_profile_normalize(profile) + } + + renv_bootstrap_profile_set <- function(profile) { + profile <- renv_bootstrap_profile_normalize(profile) + if (is.null(profile)) + Sys.unsetenv("RENV_PROFILE") + else + Sys.setenv(RENV_PROFILE = profile) + } + + renv_bootstrap_profile_normalize <- function(profile) { + + if (is.null(profile) || profile %in% c("", "default")) + return(NULL) + + profile + + } + + renv_bootstrap_path_absolute <- function(path) { + + substr(path, 1L, 1L) %in% c("~", "/", "\\") || ( + substr(path, 1L, 1L) %in% c(letters, LETTERS) && + substr(path, 2L, 3L) %in% c(":/", ":\\") + ) + + } + + renv_bootstrap_paths_renv <- function(..., profile = TRUE, project = NULL) { + renv <- Sys.getenv("RENV_PATHS_RENV", unset = "renv") + root <- if (renv_bootstrap_path_absolute(renv)) NULL else project + prefix <- if (profile) renv_bootstrap_profile_prefix() + components <- c(root, renv, prefix, ...) + paste(components, collapse = "/") + } + + renv_bootstrap_project_type <- function(path) { + + descpath <- file.path(path, "DESCRIPTION") + if (!file.exists(descpath)) + return("unknown") + + desc <- tryCatch( + read.dcf(descpath, all = TRUE), + error = identity + ) + + if (inherits(desc, "error")) + return("unknown") + + type <- desc$Type + if (!is.null(type)) + return(tolower(type)) + + package <- desc$Package + if (!is.null(package)) + return("package") + + "unknown" + + } + + renv_bootstrap_user_dir <- function() { + dir <- renv_bootstrap_user_dir_impl() + path.expand(chartr("\\", "/", dir)) + } + + renv_bootstrap_user_dir_impl <- function() { + + # use local override if set + override <- getOption("renv.userdir.override") + if (!is.null(override)) + return(override) + + # use R_user_dir if available + tools <- asNamespace("tools") + if (is.function(tools$R_user_dir)) + return(tools$R_user_dir("renv", "cache")) + + # try using our own backfill for older versions of R + envvars <- c("R_USER_CACHE_DIR", "XDG_CACHE_HOME") + for (envvar in envvars) { + root <- Sys.getenv(envvar, unset = NA) + if (!is.na(root)) + return(file.path(root, "R/renv")) + } + + # use platform-specific default fallbacks + if (Sys.info()[["sysname"]] == "Windows") + file.path(Sys.getenv("LOCALAPPDATA"), "R/cache/R/renv") + else if (Sys.info()[["sysname"]] == "Darwin") + "~/Library/Caches/org.R-project.R/R/renv" + else + "~/.cache/R/renv" + + } + + renv_bootstrap_version_friendly <- function(version, shafmt = NULL, sha = NULL) { + sha <- sha %||% attr(version, "sha", exact = TRUE) + parts <- c(version, sprintf(shafmt %||% " [sha: %s]", substring(sha, 1L, 7L))) + paste(parts, collapse = "") + } + + renv_bootstrap_exec <- function(project, libpath, version) { + if (!renv_bootstrap_load(project, libpath, version)) + renv_bootstrap_run(version, libpath) + } + + renv_bootstrap_run <- function(version, libpath) { + + # perform bootstrap + bootstrap(version, libpath) + + # exit early if we're just testing bootstrap + if (!is.na(Sys.getenv("RENV_BOOTSTRAP_INSTALL_ONLY", unset = NA))) + return(TRUE) + + # try again to load + if (requireNamespace("renv", lib.loc = libpath, quietly = TRUE)) { + return(renv::load(project = getwd())) + } + + # failed to download or load renv; warn the user + msg <- c( + "Failed to find an renv installation: the project will not be loaded.", + "Use `renv::activate()` to re-initialize the project." + ) + + warning(paste(msg, collapse = "\n"), call. = FALSE) + + } + + renv_json_read <- function(file = NULL, text = NULL) { + + jlerr <- NULL + + # if jsonlite is loaded, use that instead + if ("jsonlite" %in% loadedNamespaces()) { + + json <- tryCatch(renv_json_read_jsonlite(file, text), error = identity) + if (!inherits(json, "error")) + return(json) + + jlerr <- json + + } + + # otherwise, fall back to the default JSON reader + json <- tryCatch(renv_json_read_default(file, text), error = identity) + if (!inherits(json, "error")) + return(json) + + # report an error + if (!is.null(jlerr)) + stop(jlerr) + else + stop(json) + + } + + renv_json_read_jsonlite <- function(file = NULL, text = NULL) { + text <- paste(text %||% readLines(file, warn = FALSE), collapse = "\n") + jsonlite::fromJSON(txt = text, simplifyVector = FALSE) + } + + renv_json_read_default <- function(file = NULL, text = NULL) { + + # find strings in the JSON + text <- paste(text %||% readLines(file, warn = FALSE), collapse = "\n") + pattern <- '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]' + locs <- gregexpr(pattern, text, perl = TRUE)[[1]] + + # if any are found, replace them with placeholders + replaced <- text + strings <- character() + replacements <- character() + + if (!identical(c(locs), -1L)) { + + # get the string values + starts <- locs + ends <- locs + attr(locs, "match.length") - 1L + strings <- substring(text, starts, ends) + + # only keep those requiring escaping + strings <- grep("[[\\]{}:]", strings, perl = TRUE, value = TRUE) + + # compute replacements + replacements <- sprintf('"\032%i\032"', seq_along(strings)) + + # replace the strings + mapply(function(string, replacement) { + replaced <<- sub(string, replacement, replaced, fixed = TRUE) + }, strings, replacements) + + } + + # transform the JSON into something the R parser understands + transformed <- replaced + transformed <- gsub("{}", "`names<-`(list(), character())", transformed, fixed = TRUE) + transformed <- gsub("[[{]", "list(", transformed, perl = TRUE) + transformed <- gsub("[]}]", ")", transformed, perl = TRUE) + transformed <- gsub(":", "=", transformed, fixed = TRUE) + text <- paste(transformed, collapse = "\n") + + # parse it + json <- parse(text = text, keep.source = FALSE, srcfile = NULL)[[1L]] + + # construct map between source strings, replaced strings + map <- as.character(parse(text = strings)) + names(map) <- as.character(parse(text = replacements)) + + # convert to list + map <- as.list(map) + + # remap strings in object + remapped <- renv_json_read_remap(json, map) + + # evaluate + eval(remapped, envir = baseenv()) + + } + + renv_json_read_remap <- function(json, map) { + + # fix names + if (!is.null(names(json))) { + lhs <- match(names(json), names(map), nomatch = 0L) + rhs <- match(names(map), names(json), nomatch = 0L) + names(json)[rhs] <- map[lhs] + } + + # fix values + if (is.character(json)) + return(map[[json]] %||% json) + + # handle true, false, null + if (is.name(json)) { + text <- as.character(json) + if (text == "true") + return(TRUE) + else if (text == "false") + return(FALSE) + else if (text == "null") + return(NULL) + } + + # recurse + if (is.recursive(json)) { + for (i in seq_along(json)) { + json[i] <- list(renv_json_read_remap(json[[i]], map)) + } + } + + json + + } + + # load the renv profile, if any + renv_bootstrap_profile_load(project) + + # construct path to library root + root <- renv_bootstrap_library_root(project) + + # construct library prefix for platform + prefix <- renv_bootstrap_platform_prefix() + + # construct full libpath + libpath <- file.path(root, prefix) + + # run bootstrap code + renv_bootstrap_exec(project, libpath, version) + + invisible() + +}) diff --git a/toPdfViaTempFile14132-0.html b/toPdfViaTempFile14132-0.html new file mode 100644 index 0000000..8185489 --- /dev/null +++ b/toPdfViaTempFile14132-0.html @@ -0,0 +1,1658 @@ + + + + + + + + + + + + +webResearch analysis results + + + + + + + + + +
+ +
+ +
+
+

webResearch analysis results

+
+ + + +
+ + +
+
Published
+
+

November 8, 2024

+
+
+ + +
+ + + +
+ + + + + + + +
+

Introduction

+
+
+

Methods

+

Analyses were conducted in R version 4.4.1 using the web-based data analysis tool ‘webResearcher’ version 0.0.0.9000.

+
+
+

Results

+

Below is the baseline characteristics plotted.

+
+
+
+ + + ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CharacteristicN = 2001
Chemotherapy Treatment
+
    Drug A98 (49%)
    Drug B102 (51%)
Age47 (38, 57)
    Unknown11
Marker Level (ng/mL)0.64 (0.22, 1.41)
    Unknown10
T Stage
+
    T153 (27%)
    T254 (27%)
    T343 (22%)
    T450 (25%)
Grade
+
    I68 (34%)
    II68 (34%)
    III64 (32%)
Tumor Response61 (32%)
    Unknown7
Patient Died112 (56%)
Months to Death/Censor22.4 (15.9, 24.0)
1 n (%); Median (Q1, Q3)
+ +
+
+
+

Here are the regression results.

+
+
+
+ + + ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CharacteristicBeta95% CI1p-value
trt
+

+

+
    Drug A
+
    Drug B-0.41-4.9, 4.10.9
Marker Level (ng/mL)-0.14-2.8, 2.5>0.9
T Stage
+

+

+
    T1
+
    T22.1-4.0, 8.10.5
    T32.4-4.2, 9.10.5
    T4-3.2-9.7, 3.40.3
Grade
+

+

+
    I
+
    II0.18-5.5, 5.8>0.9
    III1.7-3.7, 7.10.5
Tumor Response5.00.00, 100.050
Patient Died3.1-3.7, 9.90.4
Months to Death/Censor-0.14-0.79, 0.510.7
1 CI = Confidence Interval
+ +
+
+
+
+
+

Discussion

+

Good luck on your further work!

+
+ +
+ + +
+ + + + diff --git a/toPdfViaTempFile14132-1.pdf b/toPdfViaTempFile14132-1.pdf new file mode 100644 index 0000000..e69de29 diff --git a/webResearch.Rproj b/webResearch.Rproj new file mode 100644 index 0000000..69fafd4 --- /dev/null +++ b/webResearch.Rproj @@ -0,0 +1,22 @@ +Version: 1.0 + +RestoreWorkspace: No +SaveWorkspace: No +AlwaysSaveHistory: Default + +EnableCodeIndexing: Yes +UseSpacesForTab: Yes +NumSpacesForTab: 2 +Encoding: UTF-8 + +RnwWeave: Sweave +LaTeX: pdfLaTeX + +AutoAppendNewline: Yes +StripTrailingWhitespace: Yes +LineEndingConversion: Posix + +BuildType: Package +PackageUseDevtools: Yes +PackageInstallArgs: --no-multiarch --with-keep.source +PackageRoxygenize: rd,collate,namespace