按行对 Dataframe 中的非缺失列求和

iezvtpos  于 2023-05-26  发布在  其他
关注(0)|答案(1)|浏览(131)

我试图从一个数据框的选择中计算非缺失列的总数。我可以用下面的代码来实现:

data %>%
  select(
    Rftrialnum,
    Rfdaterando,
    OID1treatmentcycle,
    OID2treatmentcycle,
    OID3treatmentcycle,
    OID4treatmentcycle,
    OID5treatmentcycle,
    OID6treatmentcycle,
    Eoipptpreg,
    Eoicompletedoi
  ) %>%
  rowwise() %>%
  mutate(
    count_cycle = sum(across(ends_with("treatmentcycle"), ~ !is.na(.)))
  )

它对从OID1treatmentcycleOID6treatmentcycle的非缺失值的数量求和,并保存为新变量cycle_count。然而,它使用rowwise(),考虑到 Dataframe 有数千行,这是非常慢的。有没有更有效的方法来做到这一点?

yqlxgs2m

yqlxgs2m1#

至少有三种变体。
考虑10 x 3示例 Dataframe d

d <- structure(list(A = c(5L, 3L, 1L, 3L, 5L, 2L, 1L, 2L, 5L, 2L), 
    B = c(5L, 2L, 3L, NA, 3L, 5L, 1L, 4L, 4L, 5L), C = c(1L, 
    1L, 4L, 1L, 3L, 5L, 4L, 3L, 5L, 1L)), class = "data.frame", row.names = c(NA, 
-10L))

1.与碱R:

d$na_count <-  d |> apply(1, \(xs) sum(is.na(xs)))

1.使用dplyr,逐行改变(您的版本):

d |>  rowwise() |> mutate(na_count = sum(across(everything(), ~ !is.na(.))))

1.使用dplyr的c_across进行跨列计算:

count_na = \(xs) sum(is.na(xs)) ## helper function
d |>  rowwise() |> mutate(na_count = count_na(c_across(everything())))

速度(中位数为100次重复,使用{microbenchmark}测量)

base R:    101.95 microseconds
`across`:   28.06 milliseconds
`c_across`: 18.77 milliseconds

因此,您可以使用c_across获得一些速度,但base R的速度要快180倍,正如@Leon Samson所指出的那样。

相关问题