Lili
Lili

Reputation: 47

How do I create columns based on the number of events in other columns using tidyverse?

I have a dataset that looks like this:

dataset

I want to do a d' prime analysis. To do that, I need to have a data frame that tells me how many times the subject said "yes" to a target (hit), "no" to a target (miss), "yes" to a foil (false alarm), and "no" to a foil (correctly rejected). I need to do that but have different rows per condition (A, B, C).

How can I do that in R using tidyverse?

You can recreate a small portion of my data with this code:

structure(list(id = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1), condition = c("A", "A", "A", "A", "A", "A", "B", 
"B", "B", "B", "B", "B", "C", "C", "C", "C", "C", "C"), ft = c("foil", 
"target", "target", "target", "foil", "foil", "target", "foil", 
"target", "target", "foil", "foil", "foil", "target", "target", 
"foil", "target", "foil"), response = c("no", "yes", "yes", "yes", 
"yes", "no", "yes", "no", "yes", "yes", "no", "no", "no", "no", 
"yes", "no", "no", "no"), noise_signal = c("corr_rej", "hit", 
"hit", "hit", "false_a", "corr_rej", "hit", "corr_rej", "hit", 
"hit", "corr_rej", "corr_rej", "corr_rej", "miss", "hit", "corr_rej", 
"miss", "corr_rej")), row.names = c(NA, -18L), class = c("tbl_df", 
"tbl", "data.frame"))

I want the final data frame to look like this:

enter image description here

Upvotes: 0

Views: 48

Answers (3)

akrun
akrun

Reputation: 887213

With data.table

library(data.table)
dcast(setDT(df), condition ~ noise_signal, length)
#   condition corr_rej false_a hit miss
#1:         A        2       1   3    0
#2:         B        3       0   3    0
#3:         C        3       0   1    2

Or using base R

table(df[c('condition', 'noise_signal')])

Upvotes: 0

arg0naut91
arg0naut91

Reputation: 14764

I agree that best way would be by pivoting since you already have the information; however, you could also summarise it as:

library(dplyr)

df %>%
  group_by(id, condition) %>%
  summarise(hit = sum(response[ft == 'target'] == 'yes'),
            miss = sum(response[ft == 'target'] == 'no'),
            corr_rej = sum(response[ft == 'foil'] == 'no'),
            false_a = sum(response[ft == 'foil'] == 'yes')
            )

Output:

# A tibble: 3 x 6
# Groups:   id [1]
     id condition   hit  miss corr_rej false_a
  <dbl> <chr>     <int> <int>    <int>   <int>
1     1 A             3     0        2       1
2     1 B             3     0        3       0
3     1 C             1     2        3       0

Upvotes: 0

qdread
qdread

Reputation: 3953

Sum up the number of events by signal category and condition, then pivot the data frame so that each category is in its own column:

dat %>% 
  group_by(condition, noise_signal) %>%
  summarize(n = n()) %>%
  pivot_wider(id_cols = condition, 
              names_from = noise_signal, 
              values_from = n, 
              values_fill = list(n = 0))

output:

# A tibble: 3 x 5
# Groups:   condition [3]
  condition corr_rej false_a   hit  miss
  <chr>        <int>   <int> <int> <int>
1 A                2       1     3     0
2 B                3       0     3     0
3 C                3       0     1     2

Upvotes: 3

Related Questions