R语言 检查右边的列是否每一行都有特定的值

zd287kbt  于 2023-09-27  发布在  其他
关注(0)|答案(3)|浏览(91)

我目前有一个数据如下

df <- data.frame( ID = c('A','B','C'),
                  Jan = c('N','x1','N'),
                  Feb = c('N','x1','x1'),
                  Mar = c('x1','x5','x1'),
                  Apr = c('x1','x1','x1'),
                  May = c('x5','x1','x1'),
                  Jun = c('x3','x1','N'),
                  Jul = c('x1','x7','N'),
                  Aug = c('x1','x1','x1'),
                  Sep = c('x6','N','x1'),
                  Oct = c('x1','x2','x1'),
                  Nov = c('x1','x1','x1'),
                  Dec = c('x7','x1','x1'),
                  month_num = c(3,5,2))    
df
  ID Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec month_num
1  A   N   N  x1  x1  x5  x3  x1  x1  x6  x1  x1  x7         3
2  B  x1  x1  x5  x1  x1  x1  x7  x1   N  x2  x1  x1         5
3  C   N  x1  x1  x1  x1   N   N  x1  x1  x1  x1  x1         2

我尝试在每个ID的month_num列中指定的月份号之后的月份(列)上标识值N的编号。
在我上面创建的示例数据中,ID A的month_num是3(= March)。4月~ 12月没有N,所以ID A的输出应该是0。对于ID B,month_num为5(= May),September列中有一个N,因此ID B的输出应为1。同样,对于ID C,输出应为2。
我拥有的数据非常大,每个ID可能有多行,列值不同。
我能得到一些帮助如何实现这一点吗?先谢谢你了。

u5i3ibmn

u5i3ibmn1#

我认为,如果我们重新定义long,并明确表示月份有一个我们想要计算的内在顺序,这会更容易。然后,它可以是一个summarize,基于计数"N"出现在所需的月份之后,对于每个ID。

library(tidyverse)
df |>
  pivot_longer(-c(ID, month_num)) %>%
  mutate(month_no = as.numeric(factor(name, levels = month.abb))) %>%
  summarize(count = sum(value == "N" & month_no > month_num), .by = ID)
    
# A tibble: 3 × 2
  ID    count
  <chr> <int>
1 A         0
2 B         1
3 C         2

或者与原始数据合并:

df |> left_join(df %>%
  pivot_longer(-c(ID, month_num)) %>%
  mutate(month_no = as.numeric(factor(name, levels = month.abb))) %>%
  summarize(count = sum(value == "N" & month_no > month_num), .by = ID))
v440hwme

v440hwme2#

df$res <- rowSums(col(df[,2:13]) > df$month_num & df[,2:13] == "N")
df
#>   ID Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec month_num res
#> 1  A   N   N  x1  x1  x5  x3  x1  x1  x6  x1  x1  x7         3   0
#> 2  B  x1  x1  x5  x1  x1  x1  x7  x1   N  x2  x1  x1         5   1
#> 3  C   N  x1  x1  x1  x1   N   N  x1  x1  x1  x1  x1         2   2
ruarlubt

ruarlubt3#

首先,每当单元格值为“N”时,我们将Jan到Dec列转换为逻辑值,即TRUE。然后我们将数据集split()到一个列表中,其中每个条目包含一行。我们将该列表和df$month_num输入到purrr::map2()中,并将month_num中指定的月份值之前的所有值强制为FALSE。我们将列表绑定回 Dataframe ,并通过应用rowSums()获得所需的输出。

library(tidyverse)

df$output <-
  df |>
  mutate(across(Jan:Dec, \(x) x == "N")) |>
  select(Jan:Dec) |>
  split(1:nrow(df)) |>
  map2(df$month_num, \(x, y) x |>
         mutate(across(all_of(0:y), \(z) FALSE))) |>
  list_rbind() |>
  rowSums()

df
#>   ID Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec month_num output
#> 1  A   N   N  x1  x1  x5  x3  x1  x1  x6  x1  x1  x7         3      0
#> 2  B  x1  x1  x5  x1  x1  x1  x7  x1   N  x2  x1  x1         5      1
#> 3  C   N  x1  x1  x1  x1   N   N  x1  x1  x1  x1  x1         2      2

我怀疑有一种方法可以用dplyr::rowwise()做到这一点,可能会更优雅一点。

相关问题