J'ai un bloc de données avec une colonne de type caractère contenant des chaînes de nombres délimitées par des virgules, c'est-à-dire 1, 2, 3, 4 . J'ai une fonction personnalisée que je voudrais appliquer à chaque valeur par ligne dans la colonne afin d'obtenir une nouvelle valeur que je peux stocker dans une nouvelle colonne du bloc de données df.

Frame de données initiale

A B str
1 1 1, 2, 5
1 2 NA
2 1 NA
2 2 1, 3

Frame de données finale

A B str      res
1 1 1, 2, 5  2
1 2 NA       0
2 1 NA       0
2 2 1, 3     1

Ceci est ma fonction personnalisée getCounts

getCounts <- function(str, x, y){
  if (is.na(str)){
    return(as.integer(0))
  }
  vec <- as.integer(unlist(strsplit(str, ',')))
  count <- 0
  for (i in vec) {
    if (i >= x & i <= y){
      count <- count + 1
    }
  }
  return(as.integer(count))
}


J'ai initialement essayé d'utiliser lapply car il semblait que cela convenait mieux sur la base d'autres messages, mais j'ai continué à obtenir une erreur telle que :

df <- df %>% mutate(res = lapply(df$str, getCounts(df$str, 0, 2)))
Error: Problem with `mutate()` input `res`. x missing value where TRUE/FALSE needed i Input `res` is `lapply(df$str, getCounts(df$str, 0, 2))`

La seule chose qui semble fonctionner, c'est lorsque j'utilise mapply, mais je ne comprends pas vraiment pourquoi et s'il existe une meilleure façon de le faire.

df <- df %>%mutate(res = mapply(getCounts, df$str, 0, 2))
0
fastlanes 18 mars 2021 à 03:50

3 réponses

Meilleure réponse

Si je lis bien, vous devriez pouvoir simplement utiliser rowwise() :

df %>%
  rowwise() %>%
  mutate(res = getCounts(str, 0, 2)) %>%
  ungroup()

Avec vos données:

data.frame(
    A = c(1,1,2,2),
    B = c(1,2,1,2),
    str = c('1, 2, 5', NA, NA, '1, 3')
) -> df

getCounts <- function(str, x, y){
    if (is.na(str)){
        return(as.integer(0))
    }
    vec <- as.integer(unlist(strsplit(str, ',')))
    count <- 0
    for (i in vec) {
        if (i >= x & i <= y){
            count <- count + 1
        }
    }
    return(as.integer(count))
}

library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union

df %>%
    rowwise() %>%
    mutate(res = getCounts(str, 0, 2)) %>%
    ungroup()
#> # A tibble: 4 x 4
#>       A     B str       res
#>   <dbl> <dbl> <chr>   <int>
#> 1     1     1 1, 2, 5     2
#> 2     1     2 <NA>        0
#> 3     2     1 <NA>        0
#> 4     2     2 1, 3        1

Créé le 17/03/2021 par le package reprex (v1.0.0)

1
Matt Kaye 18 mars 2021 à 01:02

Une simple mutation fera l'affaire, sans rowwise

library(stringr) 

df$res <- str_count(df$str, ',') 

Ou avec dplyr

df  %>% mutate(res = str_count(str, ',')) 
0
AnilGoyal 18 mars 2021 à 00:58

Vous pouvez essayer Vectorize

df %>%
  mutate(res = Vectorize(getCounts)(str, 0, 2))

Ou sapply

df %>%
  mutate(res = sapply(str, getCounts, x = 0, y = 2))
1
ThomasIsCoding 18 mars 2021 à 00:58