【问题标题】:Why doesn't operator %in% work with tibbles?为什么运算符 %in% 不能与小标题一起使用?
【发布时间】:2021-11-19 03:32:42
【问题描述】:

我正在使用 tibble 数据框,我需要对其进行子集化,只留下变量“代码”与所选代码向量匹配的行。最近我进入了dplyr的世界,所以我尝试使用tibbles和%>%

例如,设codedf 为:

v_code <-c(314480505000001, 314480505000002, 314480505000003, 
          314480505000004, 314480505000005, 314480505000006, 
          314480505000007, 314480505000008, 314480505000009, 
          314480505000010)
code<-tibble(code=v_code)
v_df <- c(314470605000018, 314470605000019, 314470605000020, 
            314470605000021, 314470605000022, 314480505000001, 
            314480505000002, 314480505000003, 314480505000004, 
            314480505000005, 314480505000006, 314480505000007, 
            314480505000008, 314480505000009, 314480505000010)
df <- tibble (v_df, da = 1:15)
df2 <- data.frame(v_df, da = 1:15)

所以,如果我尝试:

df2[which(df2$v_df %in% v_code),]

我得到了我想要的,但使用了小标题:

df %>% filter(v_df %in% code)

我明白了

# A tibble: 0 x 2
# ... with 2 variables: v_df <dbl>, da <int>

同样,输入which(tibble(v_df) %in% code) 会返回integer(0)

我尝试将codev_df 转换为字符,但我也不起作用。

我会感谢任何帮助。

【问题讨论】:

  • filter(df, v_df %in% unlist(code)) 有效。两件事:(1)如果code 有多个列,它会检查所有列; (2) 如果code 中的所有列都不相同class(.),那么在连接不同类对象时,由于类转换,您的比较测试可能会略有不同。

标签: r dplyr tibble


【解决方案1】:

我试图在这里解决这个问题,希望它能帮助您了解%in% 的工作原理,以及何时以及如何使用它。

您的示例不起作用的原因是code 是一个小标题。如果code 是一个向量(v_code),那么它将起作用。例如:

df %>% filter(v_df %in% v_code)

# # A tibble: 10 x 2
#      v_df    da
#     <dbl> <int>
# 1 3.14e14     6
# 2 3.14e14     7
# 3 3.14e14     8
# 4 3.14e14     9
# 5 3.14e14    10
# 6 3.14e14    11
# 7 3.14e14    12
# 8 3.14e14    13
# 9 3.14e14    14
# 10 3.14e14   15

更多详情请见?`%in%`,简而言之:

x %in% 表

x = vector 或 NULL:要匹配的值。支持长向量
table = vector 或 NULL:要匹配的值。不支持长向量。

当使用%in% 进行过滤时,在此示例中,您提供的列是x,它被视为一个向量,然后与您提供的table 向量进行比较。

我想这可能有点令人困惑,因为您可以提供一个 tibble 列作为第一个参数,但第二个参数必须是一个向量。为了更清楚为什么这不起作用,想象一下如果code tibble 有多个列 - %in% 将使用哪一列进行比较?

但是,如果 xtable 在同一个 tibble 中,它们看起来都可以是列。例如,让我们创建一个包含 2 列的 tibble 来比较:

tibble(
  x = letters[1:10], 
  y = letters[c(1:5, 8:6, 9:10)]
  ) %>% 
  mutate(
    match = x == y
  ) %>% 
  {. ->> my_tibb}

my_tibb

# # A tibble: 10 x 3
#    x     y     match
#    <chr> <chr> <lgl>
# 1  a     a     TRUE 
# 2  b     b     TRUE 
# 3  c     c     TRUE 
# 4  d     d     TRUE 
# 5  e     e     TRUE 
# 6  f     h     FALSE
# 7  g     g     TRUE 
# 8  h     f     FALSE
# 9  i     i     TRUE 
# 10 j     j     TRUE

现在,我们使用%in% 来查看x 是否与y 匹配。当然,对于这个例子,这可以使用x == ymatch == TRUE 来完成,但这展示了它仍然是如何工作的。

my_tibb %>% 
  rowwise %>% 
  filter(
    x %in% y
  )

# # A tibble: 8 x 3
# # Rowwise: 
#   x     y     match
#   <chr> <chr> <lgl>
# 1 a     a     TRUE 
# 2 b     b     TRUE 
# 3 c     c     TRUE 
# 4 d     d     TRUE 
# 5 e     e     TRUE 
# 6 g     g     TRUE 
# 7 i     i     TRUE 
# 8 j     j     TRUE 

或者,如果您的 table 对象是一个本身包含向量的列,那么 %in% 仍然可以使用。在这个例子中,我们创建了一个列z_list,它是一个包含 6 个随机字母的列表。这被强制转换为一个字符串 (z_string),这样我们就可以在 tibble 控制台预览中看到它们是哪些字母:

set.seed(3)

tibble(
  x = letters[1:10]
) %>% 
  rowwise %>%
  mutate(
    z_list = list(runif(6, min = 1, max = 26) %>%
               round %>%
               letters[.]),
    z_string = str_c(z_list, collapse = ', ')
  ) %>% 
  {. ->> my_tibb2}

my_tibb2

# # A tibble: 10 x 3
# # Rowwise: 
#    x     z_list    z_string        
#    <chr> <list>    <chr>           
# 1  a     <chr [6]> e, u, k, i, p, p
# 2  b     <chr [6]> d, h, o, q, n, n
# 3  c     <chr [6]> n, o, w, v, d, s
# 4  d     <chr [6]> w, h, g, a, d, c
# 5  e     <chr [6]> g, u, p, x, o, t
# 6  f     <chr [6]> j, j, e, l, g, i
# 7  g     <chr [6]> w, f, o, f, h, u
# 8  h     <chr [6]> e, o, k, h, b, d
# 9  i     <chr [6]> i, u, g, f, w, z
# 10 j     <chr [6]> v, x, m, g, d, h

然后我们可以使用%in% 来查看x 何时在z_list 列中:

# # A tibble: 3 x 3
# # Rowwise: 
#   x     z_list    z_string        
#   <chr> <list>    <chr>           
# 1 d     <chr [6]> w, h, g, a, d, c
# 2 h     <chr [6]> e, o, k, h, b, d
# 3 i     <chr [6]> i, u, g, f, w, z

x %in% z_string 不起作用,因为z_string 是由多个字母组成的字符串(如单词),因此单字母字符串 (x) 无法匹配。

如果您确实想查看单词中是否包含字母 (x),则必须使用 str_extract_all() 将单词拆分为单独的字母并将其放入一个列表中,如下所示。

my_tibb2 %>%
  mutate(
    word = str_replace_all(z_string, ', ', ''), 
    word_list = str_extract_all(word, boundary('character'))
  ) %>% 
  {. ->> my_tibb3}

# # A tibble: 10 x 5
# # Rowwise: 
#     x     z_list    z_string         word   word_list
#     <chr> <list>    <chr>            <chr>  <list>   
#  1  a     <chr [6]> e, u, k, i, p, p eukipp <chr [6]>
#  2  b     <chr [6]> d, h, o, q, n, n dhoqnn <chr [6]>
#  3  c     <chr [6]> n, o, w, v, d, s nowvds <chr [6]>
#  4  d     <chr [6]> w, h, g, a, d, c whgadc <chr [6]>
#  5  e     <chr [6]> g, u, p, x, o, t gupxot <chr [6]>
#  6  f     <chr [6]> j, j, e, l, g, i jjelgi <chr [6]>
#  7  g     <chr [6]> w, f, o, f, h, u wfofhu <chr [6]>
#  8  h     <chr [6]> e, o, k, h, b, d eokhbd <chr [6]>
#  9  i     <chr [6]> i, u, g, f, w, z iugfwz <chr [6]>
# 10  j     <chr [6]> v, x, m, g, d, h vxmgdh <chr [6]>

然后,我们可以像以前一样使用filter()

my_tibb3 %>% 
  filter(
    x %in% word_list
  )

# # A tibble: 3 x 5
# # Rowwise: 
#   x     z_list    z_string         word   word_list
#   <chr> <list>    <chr>            <chr>  <list>   
# 1 d     <chr [6]> w, h, g, a, d, c whgadc <chr [6]>
# 2 h     <chr [6]> e, o, k, h, b, d eokhbd <chr [6]>
# 3 i     <chr [6]> i, u, g, f, w, z iugfwz <chr [6]>

【讨论】:

    【解决方案2】:
    library(tidyverse)
    
    v_code <-c(314480505000001, 314480505000002, 314480505000003, 
               314480505000004, 314480505000005, 314480505000006, 
               314480505000007, 314480505000008, 314480505000009, 
               314480505000010)
    code<-tibble(code=v_code)
    v_df <- c(314470605000018, 314470605000019, 314470605000020, 
              314470605000021, 314470605000022, 314480505000001, 
              314480505000002, 314480505000003, 314480505000004, 
              314480505000005, 314480505000006, 314480505000007, 
              314480505000008, 314480505000009, 314480505000010)
    df <- tibble (v_df, da = 1:15)
    df2 <- data.frame(v_df, da = 1:15)
    
    df %>% filter(v_df %in% code$code)
    

    输出

    # A tibble: 10 x 2
          v_df    da
         <dbl> <int>
     1 3.14e14     6
     2 3.14e14     7
     3 3.14e14     8
     4 3.14e14     9
     5 3.14e14    10
     6 3.14e14    11
     7 3.14e14    12
     8 3.14e14    13
     9 3.14e14    14
    10 3.14e14    15
    

    【讨论】:

    • 好的,但 code$code 不是小标题。所以,重点是:在运算符 %in% 之后我是否总是需要一个向量(而不是小标题)?
    • 当然可以。运算符 %in% 如何知道它应该比较哪个变量值?除非code 变量包含在df 中。但是,它必须与df 中的其他变量的长度相同。
    • %in% 运算符在 R 中,用于识别元素是否属于向量或 Dataframe。如果你写 df%&gt;% filter (vdf% in% vscode) 这也可以正常工作。
    猜你喜欢
    • 2022-12-03
    • 1970-01-01
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-09
    • 1970-01-01
    相关资源
    最近更新 更多