簡體   English   中英

特定行 dplyr 中列子集的條件行和

[英]Conditional rowwise sum of subset of columns in specific row dplyr

我的問題有點棘手:我正在研究數據編輯,並且我即將找到正確的解決方案。 得到一個 dataframe 像這樣:

ID   name   var1  var2  var3 var_total
1     a       1     1    2       4
2     b       2     3    2       7
3     c       1    -1   -1       1

其中var_total是從 var1 到 var3 的每個大於零的數字的總和。 比如說,在 ID == 2 上,我需要將 var2 更改為 -1,這樣做:

 df %>% mutate(var2 = if_else(ID == 2, -1, var2))

這帶來了:

ID   name   var1  var2  var3 var_total
1     a       1     1    2       4
2     b       2    -1    2       7
3     c       1    -1   -1       1

問題是,我需要找到一種方法來自動重新計算該行的var_total 我知道如何為整個 dataframe 做到這一點,但這有點慢:

df %>%
  rowwise() %>%
  mutate(var_total = {
    x <- c_across(starts_with('var'))
    sum(x[x > 0])
    })

有沒有辦法只對選定的ID執行此操作? 在這種情況下,我最終的 dataframe 將是:

ID   name   var1  var2  var3 var_total
1     a       1     1    2       4
2     b       2    -1    2       4
3     c       1    -1   -1       1

謝謝!

如果您想有效地更新單行(或行的一小部分),我會使用直接分配,而不是dplyr

var_cols = grep(names(df), pattern = "var[0-9]+", value = T)
recalc_id = 2
df[df$ID %in% recalc_id, "var_total"] = apply(df[df$ID %in% recalc_id, var_cols], 1, \(x) sum(x[x > 0]))

正如 akrun 在評論中指出的那樣,如果它只是一行,則可以跳過apply

i = which(df$ID == recalc_id)
row = unlist(df[i, var_cols])
df$var_total[i] = sum(row[row > 0])

對於dplyr解決方案,這與dplyr::case_when相同:

df = df %>%
  rowwise() %>%
  mutate(var_total = case_when(
      ID %in% 2 ~{
        x <- c_across(starts_with('var[0-9]+'))
        sum(x[x > 0])
      },
      TRUE ~ var_total
    )
  )

(請注意,在這兩種情況下,我們都需要將列名模式更改為在總和中包括var_total 。)

rowwise會破壞一些矢量化並減慢速度,因此,如果您非常擔心重新計算總和“太慢”的效率,我強烈推薦base解決方案。 您甚至可能會找到一個非條件基本解決方案,該解決方案對於這種逐行操作來說足夠快。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM