Home > Software engineering >  Counting instances of a string in one dataframe, then attaching the result to a row in another dataf
Counting instances of a string in one dataframe, then attaching the result to a row in another dataf

Time:01-13

So here is part of an example dataset I'm working with:

   `D1`    `D2`        'D3'     `D4`     `D5`     `D6`     `D7`
   <chr>   <chr>      <dbl>    <dbl>    <dbl>    <dbl>    <dbl>
 1 921     917          935      457      462      451      465
 2 898     E9           914      446      452      440      455
 3 817     806          814      407      412      398      411
 4 644     632          624      321      327      314      324
 5 E9      399          385      207      213      200      206
 6 136     127          127       69       72       66       66
 7 223     233          209      117      106      117      118
 8 475     E9           443      239      234      238      246
 9 684     685          665      340      341      337      348
10 816     814          828      406      409      400      412
...

This is after I've worked with it a bit, and you can see the first two columns have a couple instances of "E9" in them, which is what I'm looking to count by running this:

df2 <- df %>%  select(-c(Time))
devices$Exclusions <- str_count(df2, "E9")

Here is my final result:

  Device        ID             Exclusions
  <chr>         <int>          <int>
1 D4            145287         14
2 D5            145286         16
3 D6            145285          0
4 D7            145284          0
5 D1            145280          0
6 D2            145277          0
7 D3            145278          0

So this leads me to my problem. The devices aren't necessarily in the same order and when it counts the instances of "E9" it is simply attaching them to the other dataframe in the order those devices are in, rather than matching them up with their names. What can I add in order to add that str_count from the D1 column to the D1 row in the other dataframe, rather than just the top row?

CodePudding user response:

Here's a solution in the tidyverse.

Solution

library(tidyverse)


# ...
# Code to generate 'df'.
# ...


df_counts <- df %>%
  # Homogenize columns as text.
  mutate(across(everything(), as.character)) %>%
  # Pivot columns into a 'Device | Code' format.
  pivot_longer(everything(), names_to = "Device", values_to = "Code") %>%
  # For each device...
  group_by(Device) %>%
  # ...count how many times "E9" appears among its codes.
  summarize(Exclusions = sum(Code == "E9"))

Speculating about the structure of your devices dataset, I can enrich the result with those IDs from your sample output:

# ...
# Code to generate 'devices'.
# ...


devices <- devices %>%
  full_join(df_counts, by = "Device", keep = FALSE)

Result

Given a df dataset like your example

df <- structure(
  list(
    D1 = c("921", "898", "817", "644", "E9", "136", "223", "475", "684", "816"),
    D2 = c("917", "E9", "806", "632", "399", "127", "233", "E9", "685", "814"),
    D3 = c(935, 914, 814, 624, 385, 127, 209, 443, 665, 828),
    D4 = c(457, 446, 407, 321, 207, 69, 117, 239, 340, 406),
    D5 = c(462, 452, 412, 327, 213, 72, 106, 234, 341, 409),
    D6 = c(451, 440, 398, 314, 200, 66, 117, 238, 337, 400),
    D7 = c(465, 455, 411, 324, 206, 66, 118, 246, 348, 412)
  ),
  class = c("tbl_df", "tbl", "data.frame"),
  row.names = c(NA, -10L)
)

this workflow should yield a result for df_counts like this:

# A tibble: 7 x 2
  Device Exclusions
  <chr>       <int>
1 D1              1
2 D2              2
3 D3              0
4 D4              0
5 D5              0
6 D6              0
7 D7              0

Furthermore, given a devices dataset like your example

devices <- structure(
  list(
    Device = c("D4", "D5", "D6", "D7", "D1", "D2", "D3"),
    ID = c(145287L, 145286L, 145285L, 145284L, 145280L, 145277L, 145278L)
  ),
  class = c("tbl_df", "tbl", "data.frame"),
  row.names = c(NA, -7L)
)

this solution should yield a devices dataset like this:

# A tibble: 7 x 3
  Device     ID Exclusions
  <chr>   <int>      <int>
1 D4     145287          0
2 D5     145286          0
3 D6     145285          0
4 D7     145284          0
5 D1     145280          1
6 D2     145277          2
7 D3     145278          0
  •  Tags:  
  • Related