How to convert factor data into intervals in R?

Viewed 31

I am working on a small research project with basis on the information made available by CIS (a Spanish research institute), where unfortunately the data is really messy.

I have in P3 several options ("Better", "Same", "Worse", "Don't Know", "Don't Answer") on how Spanish people rate their present socioeconomic situation vs the one that was 6 months ago.

And in P20 there are contained all the ages of the respondents, from 16 to 92. Say, you have age 17 in row 1, age 28 in row 2, age 65 in row 3, age 43 in row 4, and so on (out of a total of 2787 rows).

The class of both P3 and P20 is factor.

What I am looking for is to see how I can organise the data in P20 in order to group it in intervals ("16-29", "30-44", "45-64", ">65", "Don't Answer"), so that I can plot this information later on.

So far, the code that I have tried is, as follows:

library(ggplot2)

set.seed(123)

CIS_data_5 <- data.frame(
  CIS$P20,
  CIS$P3
)

CIS$P3 <- factor(CIS$P3, labels = c("Better", "Same", "Worse", "Don't Know", "Don't Answer"))
CIS$P20 <- factor(CIS$P20, labels = c("16-29", "30-44", "45-64", ">65", "Don't Answer"))


ggplot(CIS, aes(P3, fill = P20)) +
  geom_bar() +
  scale_fill_manual(values = c("LightGreen", "Green"), guide = "none") +
  facet_grid(~ P20) +
  xlab("Current VS Past Individual Situation")

However, I get the following error:

Error in factor(CIS$P20, labels = c("16-29", "30-44", "45-64", ">65", : 
invalid 'labels'; length 5 should be 1 or 0

I have tried different solutions to get around this issue, namely, cut and cut2 by looking at answers for similar questions; however, this has got me nowhere.

Any help on how I could possibly tackle this issue would be enormously appreciated.

Many thanks in advance!

1 Answers

First of all, if P20 is numeric, then you should leave it numeric, don't coerce to factor.

As for how to bin numeric data, here is a way with findInterval. Define a vector of cut points (or interval end-points) and a vector of labels. find where the data lies in the intervals defined by cut_points. After taking care of the missing values, coerce to factor.

set.seed(2022)
n <- 100L
P20 <- sample(c(16:92, NA), n, TRUE)

P20labs <- c("16-29", "30-44", "45-64", ">65", "Don't Answer")
cut_points <- c(16, 30, 45, 65, Inf)

i <- findInterval(P20, cut_points)
P20_fac <- P20labs[i]
P20_fac[is.na(P20)] <- P20labs[length(P20labs)]
P20_fac <- factor(P20_fac, levels = P20labs)

P20_fac
#>   [1] >65          Don't Answer >65          >65          >65         
#>   [6] 16-29        >65          Don't Answer 16-29        16-29       
#>  [11] >65          >65          16-29        >65          45-64       
#>  [16] >65          30-44        16-29        >65          45-64       
#>  [21] >65          >65          30-44        >65          16-29       
#>  [26] 30-44        >65          >65          16-29        >65         
#>  [31] 30-44        >65          45-64        >65          45-64       
#>  [36] 45-64        >65          16-29        30-44        >65         
#>  [41] >65          45-64        16-29        45-64        >65         
#>  [46] 45-64        30-44        30-44        >65          16-29       
#>  [51] 45-64        >65          30-44        >65          30-44       
#>  [56] >65          16-29        45-64        45-64        30-44       
#>  [61] 45-64        30-44        45-64        16-29        >65         
#>  [66] 16-29        >65          45-64        45-64        30-44       
#>  [71] 45-64        30-44        >65          >65          >65         
#>  [76] 45-64        >65          45-64        30-44        45-64       
#>  [81] >65          >65          >65          >65          45-64       
#>  [86] 16-29        30-44        30-44        >65          16-29       
#>  [91] 16-29        45-64        45-64        45-64        >65         
#>  [96] >65          45-64        30-44        30-44        >65         
#> Levels: 16-29 30-44 45-64 >65 Don't Answer

Created on 2022-09-24 with reprex v2.0.2

Related