AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / Perguntas / 78689583
Accepted
James Rider
James Rider
Asked: 2024-07-01 03:21:51 +0800 CST2024-07-01 03:21:51 +0800 CST 2024-07-01 03:21:51 +0800 CST

Contar strings vazias?

  • 772

Em R, suponha que eu tenha um vetor como:

vector<-c("Red", "   ", "", "5", "")

Quero contar quantos elementos deste vetor são apenas strings vazias que consistem apenas em espaços ou nenhum espaço . Para este vetor muito curto, são apenas três . O segundo, terceiro e quinto elementos são apenas espaços ou nenhum espaço. Eles não possuem caracteres como letras, números, símbolos, etc.

Existe alguma função ou método que conte isso? Eu queria algo que pudesse usar em vetores maiores, em vez de apenas observar cada elemento do vetor.

  • 6 6 respostas
  • 150 Views

6 respostas

  • Voted
  1. s_baldur
    2024-07-01T04:28:31+08:002024-07-01T04:28:31+08:00

    Mais uma opção:

    sum(gsub(" ", "", vector, fixed = TRUE) == "")
    

    E uma variação concisa da resposta anterior:

    sum(trimws(vector) == "")
    

    Finalmente... já que estamos nos divertindo com benchmarks. Há espaço para melhorias em relação à base R, conforme mostrado por SamR usando stringi. Aqui está outro exemplo usando Rcpp onde evitamos modificar o vetor e inspecionamos caractere por caractere até o primeiro caractere sem espaço.

    cppFunction("int count_empty_cpp(CharacterVector x) {
      int count = 0, j, n;
      std::string v;
      for (int i = 0; i < x.size(); i++) {
        v = Rcpp::as<std::string>(x[i]);
        n = v.length();
        if (n == 0) {
          count++;
        } else {
          j = 0;
          while (j < n && v[j] == ' ') j++;
          if (j == n) count++;
        }
      }
      return count;
    }")
    
    • 6
  2. SamR
    2024-07-01T04:55:39+08:002024-07-01T04:55:39+08:00

    Abordagens R puras

    Você tem várias respostas excelentes de base R. Notei que você marcou stringr. Não acho que haja vantagem em usar stringraqui. No entanto, pode haver uso do pacote R para processamento de string/texto rápido, portátil, correto, consistente e conveniente em qualquer localidade ou codificação de caracteres.stringi

    stringitende a ser extremamente rápido. stringrdepende stringi(e de fato muitas stringrfunções são wrappers finos para stringifunções), portanto, se você instalou stringr, também terá o stringi.

    Ao contrário de stringr, stringitem uma função para verificar strings vazias (equivalente a !base::nzchar()), o que provavelmente é mais rápido que a comparação de strings e quase certamente mais rápido que contar os caracteres de todas as strings (incluindo as não vazias).

    library(stringi)
    sum(stri_isempty(stri_trim_both(vector)))
    # [1] 3
    

    Abordagens RCPP

    Como a resposta de S. Baldur demonstra agora, você Rcpptambém pode usar para isso.

    Isso é tão mais rápido que vou incluí-lo em uma seção separada de benchmarks abaixo, para que seja mais fácil ver as diferenças nas abordagens R puras.

    Benchmarks de R puro

    Só por diversão, fiz alguns benchmarks com vetores de até 1m de comprimento. A segunda abordagem de S. Baldur é mais rápida para vetores de comprimento 10 e 100. Com vetores de comprimento 1000 e superiores, a stringiabordagem é a mais rápida.

    insira a descrição da imagem aqui

    Se a RAM for um fator, a resposta de Ben Bolker usa consistentemente menos memória. Aqui estão os dados em formato tabular (observe que os tempos são relativos e a abordagem de memória mais rápida/menor é sempre 1).

       expression vec_length   min median `itr/sec` mem_alloc `gc/sec` n_itr  n_gc total_time
       <bch:expr>      <dbl> <dbl>  <dbl>     <dbl>     <dbl>    <dbl> <int> <dbl>   <bch:tm>
     1 bolker             10  1.95   1.65      4.91    NaN         Inf  9999     1      161ms
     2 rudolph            10  5.64   7.11      1       NaN         Inf  6099     2      483ms
     3 baldur             10  1.09   1         7.13    NaN         Inf  9999     1      111ms
     4 baldur2            10  1.05   1         6.91    NaN         NaN 10000     0      115ms
     5 thomas             10  1.55   1.92      4.11    NaN         Inf  9999     1      193ms
     6 rui                10  5.82   7.38      1.18    NaN         Inf  7046     2      472ms
     7 rui2               10  5.55   6.95      1.23    NaN         Inf  7373     3      475ms
     8 samr               10  1      1.27      6.72    NaN         NaN 10000     0      118ms
     9 bolker            100  1.56   1.57      4.30      1         Inf  9999     1      320ms
    10 rudolph           100  6.83   6.53      1.10      5.79      Inf  3892     1      487ms
    11 baldur            100  1.03   1.04      6.64      2.89      Inf  9999     1      207ms
    12 baldur2           100  1      1         6.87      3.89      Inf  9999     1      200ms
    13 thomas            100  1.64   1.58      4.19      2         NaN 10000     0      328ms
    14 rui               100  7      7.07      1         5.79      Inf  3546     1      488ms
    15 rui2              100  6.69   6.5       1.12      5.79      Inf  3904     2      482ms
    16 samr              100  1.19   1.05      6.38      2.89      NaN 10000     0      216ms
    17 bolker           1000  1.31   1.64      4.09      1         Inf  3025     1      487ms
    18 rudolph          1000  5.43   5.97      1.10      5.98      NaN   830     0      499ms
    19 baldur           1000  1.06   1.23      5.13      2.99      Inf  3109     1      399ms
    20 baldur2          1000  1      1.18      5.57      3.99      NaN  4186     0      495ms
    21 thomas           1000  1.17   1.41      4.89      2         NaN  3685     0      496ms
    22 rui              1000  7.32   6.58      1         5.98      NaN   758     0      499ms
    23 rui2             1000  7.17   5.85      1.12      5.98      NaN   853     0      500ms
    24 samr             1000  1.05   1         6.01      2.99      Inf  4439     1      486ms
    25 bolker          10000  1.77   1.61      4.39      1         NaN   355     0      501ms
    26 rudolph         10000  8.56   6.18      1.13      6.00      NaN    92     0      502ms
    27 baldur          10000  1.06   1.26      5.56      3.00      Inf   443     1      492ms
    28 baldur2         10000  1      1.21      5.69      4.00      NaN   460     0      500ms
    29 thomas          10000  1.57   1.44      4.81      2         Inf   388     1      499ms
    30 rui             10000  8.28   6.89      1         6.00      NaN    81     0      501ms
    31 rui2            10000  8.69   6.19      1.13      6.00      NaN    92     0      505ms
    32 samr            10000  1.23   1         6.69      3.00      Inf   533     1      493ms
    33 bolker         100000  1.92   1.58      4.21      1         NaN    36     0      510ms
    34 rudolph        100000  7.83   6.31      1.07      6.00      NaN     9     0      504ms
    35 baldur         100000  1.37   1.31      5.08      3.00      Inf    42     1      493ms
    36 baldur2        100000  1.45   1.37      4.96      4.00      Inf    41     1      493ms
    37 thomas         100000  1.52   1.37      4.89      2         NaN    41     0      500ms
    38 rui            100000  7.46   6.60      1         6.00      NaN     9     0      537ms
    39 rui2           100000  6.93   6.05      1.11      6.00      Inf     9     1      483ms
    40 samr           100000  1      1         6.56      3.00      NaN    55     0      500ms
    41 bolker        1000000  1.81   1.79      4.39      1         NaN     4     0      551ms
    42 rudolph       1000000  7.76   7.13      1.09      6.00      NaN     1     0      553ms
    43 baldur        1000000  1.48   1.44      5.42      3.00      Inf     4     1      447ms
    44 baldur2       1000000  1.52   1.44      5.44      4.00      Inf     4     1      445ms
    45 thomas        1000000  1.64   1.53      5.04      2         Inf     4     1      480ms
    46 rui           1000000  8.50   7.80      1         6.00      NaN     1     0      605ms
    47 rui2          1000000  7.59   6.97      1.12      6.00      NaN     1     0      541ms
    48 samr          1000000  1      1         7.88      3.00      Inf     6     1      460ms
    

    Código de referência:

    results <- bench::press(
        vec_length = 10^(1:6),
        {
            vals <- c("Red", "", " ", " ", "   ", "   ", "5", letters[1:3])
            v <- sample(vals, vec_length, replace = TRUE)
            bench::mark(
                relative = TRUE,
                bolker = sum(grepl("^ *$", v)),
                rudolph = sum(!nzchar(trimws(v))),
                baldur = sum(gsub(" ", "", v, fixed = TRUE) == ""),
                baldur2 = sum(!nzchar(gsub(" ", "", v, fixed = TRUE))),
                thomas = sum(!grepl("\\S", v)),
                rui = sum(nchar(trimws(v)) == 0),
                rui2 = sum(!nzchar(trimws(v))),
                samr = sum(stri_isempty(stri_trim_both(v)))
            )
        }
    )
    

    Rcppbenchmarks

    Incluo separadamente uma referência da count_empty_cpp()função de S. Baldur. Isso é muito mais rápido do que minha stringiabordagem, então adicionei outra Rcppfunção usando a biblioteca padrão C++, baseada fortemente na resposta à pergunta C++, Maneira eficiente de verificar se std::string possui apenas espaços .

    Rcpp::cppFunction("int count_empty_cpp2(CharacterVector x) {
      int count = 0, j, n;
      std::string str;
      for (int i = 0; i < x.size(); i++) {
        str = Rcpp::as<std::string>(x[i]);
        if(str.find_first_not_of(' ') == std::string::npos)
        {
            count++;
        }
      }
      return count;
    }")
    

    Também adicionei uma terceira Rcppfunção que analisa a expressão S subjacente de cada elemento do vetor de caracteres. Isso significa que podemos evitar a conversão de tipo nos casos em que a string está vazia. Além disso, quando precisamos examinar o conteúdo da string, eu uso CHAR()para converter o SEXPponteiro em estilo C para uma string terminada em nulo ( const char*), em vez de um C++ std::string. Isso significa que copiamos a referência (provavelmente 8 bytes por string), em vez dos dados.

    Rcpp::cppFunction("int count_empty_cpp3(CharacterVector x) {
      int count = 0;
      for (int i = 0; i < x.size(); i++) {
        SEXP elem = x[i];
        R_xlen_t len = Rf_length(elem);
        if (len == 0) {
          count++;
        } else {
          const char* str = CHAR(elem);
          bool is_empty = true;
          for (R_xlen_t j = 0; j < len; j++) {
            if (str[j] != ' ') {
              is_empty = false;
              break;
            }
          }
          if (is_empty) count++;
        }
      }
      return count;
    }")
    

    Comparei isso com as duas respostas R mais rápidas. Todas Rcppas abordagens são muito mais rápidas do que as abordagens R mais rápidas, uma vez que os comprimentos dos vetores são >1e4.

    insira a descrição da imagem aqui

    Aqui está uma tabela de resultados. Há muito poucas diferenças entre as duas primeiras Rcppabordagens. A abordagem evitando std::stringé um pouco mais rápida que as outras duas:

       expression    vec_length   min median `itr/sec` mem_alloc `gc/sec` n_itr  n_gc total_time
       <bch:expr>         <dbl> <dbl>  <dbl>     <dbl>     <dbl>    <dbl> <int> <dbl>   <bch:tm>
     1 baldur2_baser         10  1.56   1.55      1.61    NaN         Inf  9999     1    84.46ms
     2 samr_stringi          10  2.44   2.18      1       NaN         NaN 10000     0   135.71ms
     3 baldercpp             10  1.11   1.05      2.22    Inf         NaN 10000     0    61.11ms
     4 samrcpp               10  1.11   1.09      1.95    Inf         Inf  9999     1    69.62ms
     5 samrcpp2              10  1      1         2.10    Inf         Inf  9999     1    64.57ms
     6 baldur2_baser        100  2.64   2.57      1         1.35      NaN 10000     0   200.12ms
     7 samr_stringi         100  3      2.57      1.01      1         Inf  9999     1   198.57ms
     8 baldercpp            100  1.14   1.03      2.33      1.97      NaN 10000     0    85.74ms
     9 samrcpp              100  1.14   1.1       1.90      1.97      Inf  9999     1   105.58ms
    10 samrcpp2             100  1      1         2.23      1.97      Inf  9999     1    89.85ms
    11 baldur2_baser       1000  3.67   4.51      1         6.33      Inf  4408     2   481.84ms
    12 samr_stringi        1000  3.64   3.93      1.03      4.74      Inf  4591     1   488.59ms
    13 baldercpp           1000  1.45   1.41      2.77      1         Inf  9999     1   395.14ms
    14 samrcpp             1000  1.55   1.49      2.58      1         Inf  9999     1   423.62ms
    15 samrcpp2            1000  1      1         3.92      1         NaN 10000     0   278.97ms
    16 baldur2_baser      10000  4.06   5.29      1        62.8       Inf   465     3   480.15ms
    17 samr_stringi       10000  3.73   4.26      1.16     47.1       Inf   555     1   494.04ms
    18 baldercpp          10000  1.52   1.56      2.99      1         NaN  1444     0   498.64ms
    19 samrcpp            10000  1.58   1.64      3.05      1         Inf  1457     1    492.9ms
    20 samrcpp2           10000  1      1         4.79      1         NaN  2305     0   496.85ms
    21 baldur2_baser     100000  5.35   5.16      1       627.        Inf    48     2   529.89ms
    22 samr_stringi      100000  4.61   4.08      1.23    470.        Inf    54     2    484.1ms
    23 baldercpp         100000  1.51   1.53      3.34      1         NaN   152     0    501.8ms
    24 samrcpp           100000  1.57   1.57      3.31      1         NaN   150     0   500.94ms
    25 samrcpp2          100000  1      1         4.89      1         NaN   222     0    501.5ms
    26 baldur2_baser    1000000  4.46   5.04      1      6270.        Inf    27    23      2.89s
    27 samr_stringi     1000000  3.94   3.89      1.27   4702.        Inf    37    13      3.11s
    28 baldercpp        1000000  1.30   1.41      3.50      1         NaN    50     0      1.53s
    29 samrcpp          1000000  1.45   1.53      3.15      1         NaN    50     0      1.69s
    30 samrcpp2         1000000  1      1         4.65      1         NaN    50     0      1.15s
    

    Estas são strings relativamente curtas. Não vou executar mais benchmarks, mas suspeito que se as strings fossem mais longas, veríamos um benefício relativo em copiar o ponteiro em vez dos dados.

    Uma nota sobre os benchmarks

    Esses benchmarks são principalmente para diversão. As diferenças entre todas as respostas são relativamente pequenas, portanto, a menos que você repita isso muitas vezes com vetores enormes, tenha strings extremamente longas ou recursos de memória muito limitados, em vez de lançar minha própria solução Rcpp que é nanossegundos mais rápida, eu otimizaria para código legível .

    • 6
  3. ThomasIsCoding
    2024-07-01T05:00:24+08:002024-07-01T05:00:24+08:00

    Para golfe com código, provavelmente você pode estar interessado

    > sum(!grepl("\\S", vector))
    [1] 3
    
    • 6
  4. Best Answer
    2024-07-01T03:24:41+08:002024-07-01T03:24:41+08:00

    Use sum(grepl())mais uma expressão regular apropriada:

    vector<-c("Red", "   ", "", "5", "")
    sum(grepl("^ *$", vector))
    
    • ^: início da string
    • *: zero ou mais espaços
    • $: fim da string

    Se você quiser procurar por "espaço em branco" de forma mais geral (por exemplo, permitindo tabulações), use "^[[:space:]]*$", embora, como apontado em ?grep, a definição de espaço em branco dependa da localidade ...

    length(grep(...))também funcionaria, ou stringr::str_count(vector, "^ *$").

    Pelo que vale:

     microbenchmark::microbenchmark(
         bolker =  sum(grepl("^ *$", vector)),
         rudolph = sum(! nzchar(trimws(vector))),
         baldur = sum(gsub(" ", "", vector, fixed = TRUE) == ""),
        baldur2 = sum(! nzchar(gsub(" ", "", vector, fixed = TRUE))))
    
    Unit: microseconds
        expr    min      lq     mean  median      uq    max neval cld
      bolker 10.499 10.8900 12.31869 11.8020 12.7990 40.976   100 a  
     rudolph 19.306 20.0125 22.01722 20.7990 22.9480 66.815   100  b 
      baldur  2.294  2.5700  2.76420  2.7455  2.8950  3.567   100   c
     baldur2  2.294  2.4740  2.66267  2.6450  2.7755  5.130   100   c
    

    (@RuiBarradas não incluído porque é semelhante ao @KonradRudolph). Estou surpreso que a resposta de @s_baldur seja tão rápida ... mas provavelmente também vale a pena ter em mente que esta operação será rápida o suficiente para não se preocupar com eficiência, a menos que seja uma grande parte do seu fluxo de trabalho geral ...

    • 5
  5. Konrad Rudolph
    2024-07-01T03:52:10+08:002024-07-01T03:52:10+08:00

    Eu usaria nzchar()em combinação com trimws()(mesmo que a dupla negação !nzchar()torne isso um pouco estranho de ler):

    sum(! nzchar(trimws(vector)))
    # [1] 3
    
    • 4
  6. Rui Barradas
    2024-07-01T03:33:25+08:002024-07-01T03:33:25+08:00

    trimwsremove todos os espaços em branco. Então ncharobterá o número de caracteres. Compare com zero e conte apenas esses. Mas isso é cerca de 3 vezes mais lento que a resposta de Ben Bolker .

    v <- c("Red", "   ", "", "5", "")
    sum(nchar(trimws(v)) == 0)
    #> [1] 3
    

    Criado em 30/06/2024 com reprex v2.1.0


    Editar

    Com base em um comentário agora excluído,

    sum(!nzchar(trimws(v)))
    #> [1] 3
    

    Criado em 30/06/2024 com reprex v2.1.0

    • 3

relate perguntas

  • Adicionar número de série para atividade de cópia ao blob

  • A fonte dinâmica do empacotador duplica artefatos

  • Selecione linhas por grupo com 1s consecutivos

  • Lista de chamada de API de gráfico subscritoSkus estados Privilégios insuficientes enquanto os privilégios são concedidos

  • Função para criar DFs separados com base no valor da coluna

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Vue 3: Erro na criação "Identificador esperado, mas encontrado 'import'" [duplicado]

    • 1 respostas
  • Marko Smith

    Por que esse código Java simples e pequeno roda 30x mais rápido em todas as JVMs Graal, mas não em nenhuma JVM Oracle?

    • 1 respostas
  • Marko Smith

    Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores?

    • 1 respostas
  • Marko Smith

    Como faço para corrigir um erro MODULE_NOT_FOUND para um módulo que não importei manualmente?

    • 6 respostas
  • Marko Smith

    `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso?

    • 3 respostas
  • Marko Smith

    Quando devo usar um std::inplace_vector em vez de um std::vector?

    • 3 respostas
  • Marko Smith

    Um programa vazio que não faz nada em C++ precisa de um heap de 204 KB, mas não em C

    • 1 respostas
  • Marko Smith

    PowerBI atualmente quebrado com BigQuery: problema de driver Simba com atualização do Windows

    • 2 respostas
  • Marko Smith

    AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos

    • 1 respostas
  • Marko Smith

    Estou tentando fazer o jogo pacman usando apenas o módulo Turtle Random e Math

    • 1 respostas
  • Martin Hope
    Aleksandr Dubinsky Por que a correspondência de padrões com o switch no InetAddress falha com 'não cobre todos os valores de entrada possíveis'? 2024-12-23 06:56:21 +0800 CST
  • Martin Hope
    Phillip Borge Por que esse código Java simples e pequeno roda 30x mais rápido em todas as JVMs Graal, mas não em nenhuma JVM Oracle? 2024-12-12 20:46:46 +0800 CST
  • Martin Hope
    Oodini Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores? 2024-12-12 06:27:11 +0800 CST
  • Martin Hope
    sleeptightAnsiC `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso? 2024-11-09 07:18:53 +0800 CST
  • Martin Hope
    The Mad Gamer Quando devo usar um std::inplace_vector em vez de um std::vector? 2024-10-29 23:01:00 +0800 CST
  • Martin Hope
    Chad Feller O ponto e vírgula agora é opcional em condicionais bash com [[ .. ]] na versão 5.2? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench Por que um traço duplo (--) faz com que esta cláusula MariaDB seja avaliada como verdadeira? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng Por que `dict(id=1, **{'id': 2})` às vezes gera `KeyError: 'id'` em vez de um TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos 2024-03-20 03:12:31 +0800 CST
  • Martin Hope
    MarkB Por que o GCC gera código que executa condicionalmente uma implementação SIMD? 2024-02-17 06:17:14 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve