Some code examples might give others a bit better idea of what you are dealing with or what kind of processing you are doing. Note that even if you are just turning (non-date/time) strings to factors, you might not gain much as R keeps unique strings in a global string pool and character vectors are basically vectors of pointers. For example rep("foo", 100) results in a vector of 100 identical pointers and a single "foo" instance in memory, this is not too different from how unordered factors are handled, but with less overhead.
Performance-wise, you'd probably gain more if you'd focus on your use & choice of string and date/time handling routines, if you currently happen to use methods from base R (or Tidyverse packages), it might be worth looking around for some more performant alternatives. For example, stringi, stringfish for strings. For date/time consider evaluating clock, anytime, fasttime.
You might also want to prefer more specialized methods (e.g. if you care only about the first match, stop early; and don't use regex methods where fixed strings would do; if stringi::stri_replace_first_coll() does what you need, prefer that over stringi::stri_replace_all_regex(); when parsing date/time values, use multi-format parsers only when really needed).
For a collection of performance-oriented packages you could check fastverse
Split-apply-combine could make a huge difference if you can and plan to parallelize the process. "Could", as it really depends on what you are dealing with and what's the actual task. For example if your parallel tasks are really short but workers need to send back a relatively large amount of data instead of small aggregates, total time might actually increase due to introduced overhead. Your system can also play a role here, as R process forking is not supported in Windows, depending on your choice of parallel framework, this can affect worker startup and data exchange.
You also have a few plyr references here and there, the package status is retired and you'd likely get all the functionality with dplyr + purrr (if you lean towards Tidyverse). With purrr it would also be easy to switch to current parallel processing options, be it through the Futureverse packages or with purrr+ mirai (purrr::in_parallel()). Or just use mirai directly, without purrr.
Your post is also tagged with dplyr, which can be somewhat vague in this context. dplyr (the package) is not always considered the best choice for performance-oriented tasks and/or bigger datasets, this is more in the domain of data.table and perhaps collapse. On the other hand, dplyr(-like) syntax, because it is verbose, easy to read and write for humans, can be used with quite a few different packages and backends. For example dtplyr or tidytable to use dplyr syntax with data.table. Or dbplyr to use your dplyr pipelines and many common methods with SQL databases, both remote and local, without actually writing any SQL. Or arrow, to manage and process larger(and larger-than-memory) datasets. collapse syntax can also be quite close.
The issue with all these abstractions is that you can get quite far with just dplyr syntax without bothering about internals or backends those packages actually use, but at some point you will likely encounter a problem that requires you to know at least some data.table or SQL. So there's this paradox, people with data.table / SQL skills can work around most limitations and can come up with dplyr-pipelines that are running on high-performance backends and which are also easy to read by those only familiar with dplyr; but with only a dplyr background it is easy get stuck and/or accidentally trigger avoidable data copies and end up with sub-optimal performance.
My personal preference for larger (and larger-than-memory) datasets is DuckDB, it is an analytical in-process SQL database, and a fast one. Might sound intimidating, but in-process means that it is essentially effortless to install and use, for many common use cases there's no persistent DuckDB database, just use it to open existing CSV / TSV / JSON / Parquet / ... file(s), do your data thing, write results directly to file(s) or pull into R as a data.frame. It's already widely used for many types of data tasks, meaning it's easy to find help (at least for more generic DuckDB / SQL questions, maybe bit less so for anything dplyr-related that involves translation).
Perhaps start with duckplyr and its Vignettes and examples, its aim is to become a drop-in replacement for dplyr. The earlier warning about dplyr syntax as an abstraction layer still applies and one should try to process as much as possible in DuckDB and avoid early materialization in R. Knowing SQL helps to fully use DuckDB potential, but one can get quite far with just duckplyr, it provides access to most Functions – DuckDB in one way or another.
And of course there's compute time vs human time. If your current process is just slow but still works, is it worth investing hours/days/weeks/... to improve it just save a few minutes/hours over the next year or so? There are of course other factors (cummulative compute cost, cost of the delay in some foreseeable future, risks from new/experimental/unstable stack, risks from obsolete stack, etc)
Also, few related chapters from R4DS that might help: