[英]Mutating column in `dplyr` using `rowSums`
最近我偶然發現了dplyr
的奇怪行為,如果有人能提供一些見解,我會很高興。
假設我有一個數據,其中 com 列包含一些數值。 在一個簡單的場景中,我想計算rowSums
。 雖然有很多方法可以做到,這里有兩個例子:
df <- data.frame(matrix(rnorm(20), 10, 2),
ids = paste("i", 1:20, sep = ""),
stringsAsFactors = FALSE)
# works
dplyr::select(df, - ids) %>% {rowSums(.)}
# does not work
# Error: invalid argument to unary operator
df %>%
dplyr::mutate(blubb = dplyr::select(df, - ids) %>% {rowSums(.)})
# does not work
# Error: invalid argument to unary operator
df %>%
dplyr::mutate(blubb = dplyr::select(., - ids) %>% {rowSums(.)})
# workaround:
tmp <- dplyr::select(df, - ids) %>% {rowSums(.)}
df %>%
dplyr::mutate(blubb = tmp)
# works
rowSums(dplyr::select(df, - ids))
# does not work
# Error: invalid argument to unary operator
df %>%
dplyr::mutate(blubb = rowSums(dplyr::select(df, - ids)))
# workaround
tmp <- rowSums(dplyr::select(df, - ids))
df %>%
dplyr::mutate(blubb = tmp)
首先,我真的不明白是什么導致了錯誤,其次我想知道如何以一種整潔的方式實際實現一些(可行的)列的整潔計算。
編輯
問題mutate and rowSums exclude columns盡管相關,但重點在於使用rowSums
進行計算。 在這里,我很想了解為什么上面的例子不起作用。 與其說是如何解決(請參閱解決方法),不如說是了解應用朴素方法時會發生什么。
這些示例不起作用,因為您在mutate
中嵌套select
並使用裸變量名稱。 在這種情況下, select
正在嘗試執行類似的操作
> -df$ids
Error in -df$ids : invalid argument to unary operator
失敗是因為您無法否定字符串(即-"i1"
或-"i2"
沒有意義)。 以下任一配方均有效:
df %>% mutate(blubb = rowSums(select_(., "X1", "X2")))
df %>% mutate(blubb = rowSums(select(., -3)))
或者
df %>% mutate(blubb = rowSums(select_(., "-ids")))
正如@Haboryme 所建議的那樣。
select_
已棄用。 您可以使用:
library(dplyr)
df <- data.frame(matrix(rnorm(20), 10, 2),
ids = paste("i", 1:20, sep = ""),
stringsAsFactors = FALSE)
df %>%
mutate(blubb = rowSums(select(., .dots = c("X1", "X2"))))
# Or more generally:
desired_columns <- c("X1", "X2")
df %>%
mutate(blubb = rowSums(select(., .dots = all_of(desired_columns))))
select
現在可以接受裸列名稱,因此無需使用已棄用的.dots
或select_
。
以下是一些現在可行的方法。
library(dplyr)
#sum all the columns except `id`.
df %>% mutate(blubb = rowSums(select(., -ids), na.rm = TRUE))
#sum X1 and X2 columns
df %>% mutate(blubb = rowSums(select(., X1, X2), na.rm = TRUE))
#sum all the columns that start with 'X'
df %>% mutate(blubb = rowSums(select(., starts_with('X')), na.rm = TRUE))
#sum all the numeric columns
df %>% mutate(blubb = rowSums(select(., where(is.numeric))))
添加到這個舊線程是因為我搜索了這個問題然后意識到我問錯了問題。 此外,我在這個和相關問題中發現了一些對正確管道步驟方法的渴望。
這里的答案有些不直觀,因為他們試圖將 dplyr 白話與非“整潔”數據一起使用。 如果您想以 dplyr 方式進行操作,請先使用 Gather gather()
整理數據,然后使用summarise()
library(tidyverse)
df <- data.frame(matrix(rnorm(20), 10, 2),
ids = paste("i", 1:20, sep = ""),
stringsAsFactors = FALSE)
df %>% gather(key=Xn,value="value",-ids) %>%
group_by(ids) %>%
summarise(rowsum=sum(value))
#> # A tibble: 20 x 2
#> ids rowsum
#> <chr> <dbl>
#> 1 i1 0.942
#> 2 i10 -0.330
#> 3 i11 0.942
#> 4 i12 -0.721
#> 5 i13 2.50
#> 6 i14 -0.611
#> 7 i15 -0.799
#> 8 i16 1.84
#> 9 i17 -0.629
#> 10 i18 -1.39
#> 11 i19 1.44
#> 12 i2 -0.721
#> 13 i20 -0.330
#> 14 i3 2.50
#> 15 i4 -0.611
#> 16 i5 -0.799
#> 17 i6 1.84
#> 18 i7 -0.629
#> 19 i8 -1.39
#> 20 i9 1.44
如果您關心 id 無法使用arrange()
排序時的順序,請先將該列作為一個因素。
df %>%
mutate(ids=as_factor(ids)) %>%
gather(key=Xn,value="value",-ids) %>%
group_by(ids) %>%
summarise(rowsum=sum(value))
為什么要使用管道運算符? 只需寫一個表達式,例如:
rowSums(df[,sapply(df, is.numeric)])
即計算所有數字列的行和,優點是不需要指定ids
。
如果要將結果保存為數據中的列,可以使用如下所示的 data.table 語法:
dt <- as.data.table(df)
dt[, x3 := rowSums(.SD, na.rm=T), .SDcols = which(sapply(dt, is.numeric))]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.