R dplyr:使用自定义函数的按行操作
R dplyr: Row wise operations using custom function
在 pandas 中,我经常使用这样的自定义函数执行行式操作:
df = pd.DataFrame({'v1': [1, 2, 3], 'v2': [3, 4, 6], 'v3': [3, 4, 5]})
def f(row):
return(sum(row[["v1", "v3"]]) if row.v2 == 3 else 7)
df["new_col"] = df.apply(f, 1)
dplyr 中的等价物是什么?
请注意,函数 f 可能会使用许多变量,而不仅仅是 v1-v3,因此我不希望在调用函数时将它们全部命名。
编辑:我目前在 R 中的示例代码。在这个解决方案中,我传递了一个代词对象,我怀疑它是否合适。
d <- tibble(v1 = c(1,2,3), v2 = c(3,4,6), v3 = c(3,4,5))
f <- function(row){
if (row$v2 == 3) sum(something?) else 7
}
d %>% rowwise() %>% mutate(new_column = f(.data)) %>% ungroup()
edit2:预期输出。 (索引列不重要)
v1 v2 v3 new_col
0 1 3 3 4
1 2 4 4 7
2 3 6 5 7
注意:我不是在寻找这个特定问题的解决方案。我对将行传递给 R / dplyr 中的函数的一般方法感兴趣,就像 pandas 中的 apply() 一样。
将整行作为数据帧传递给函数的等效 dplyr 代码可能是:
library(tidyverse)
df <- tibble(v1 = c(1, 2, 3), v2 = c(4, 5, 6), v3 = c(7, 8, 9))
f <- function(row){
if (row$v2 == 3){
return(sum(row$v1, row$v3))
}else{
return(7)
}
}
df %>%
rowwise() %>%
do(row = as_data_frame(.)) %>%
mutate(new_col = f(row)) %>%
unnest()
输出:
# A tibble: 3 x 4
new_col v1 v2 v3
<dbl> <dbl> <dbl> <dbl>
1 4 1 3 3
2 7 2 4 4
3 7 3 6 5
如果您有一组完好无损的列,那么我建议您的函数只关注单个向量,而不是单行框架。
library(dplyr)
d <- tibble(v1 = c(1,2,3), v2 = c(3,4,6), v3 = c(3,4,5))
f <- function(v1, v2, v3) ifelse(v2 == 3, v1 + v3, 7)
d %>% rowwise() %>% mutate(new_column = f(v1, v2, v3)) %>% ungroup()
# # A tibble: 3 x 4
# v1 v2 v3 new_column
# <dbl> <dbl> <dbl> <dbl>
# 1 1 3 3 4
# 2 2 4 4 7
# 3 3 6 5 7
我用ifelse
防御,"in case"它曾用于组副行。如果您将函数定义为
,它就可以正常工作
f <- function(v1, v2, v3) if (v2 == 3) v1+v3 else 7
事实上,如果您的现实世界逻辑并不复杂,那么这不需要 rowwise()
,因此速度会快得多。 (但我不知道你真正的需求。)
选择:
d %>% mutate(new_column = purrr::pmap_dbl(list(v1,v2,v3), f))
df %>% mutate(new_col=with(.,case_when(v2 != 3 ~ 7,v2 == 3 ~ (v1 + v3))))
输出
v1 v2 v3 new_col
1 1 3 3 4
2 2 4 4 7
3 3 6 5 7
在 pandas 中,我经常使用这样的自定义函数执行行式操作:
df = pd.DataFrame({'v1': [1, 2, 3], 'v2': [3, 4, 6], 'v3': [3, 4, 5]})
def f(row):
return(sum(row[["v1", "v3"]]) if row.v2 == 3 else 7)
df["new_col"] = df.apply(f, 1)
dplyr 中的等价物是什么?
请注意,函数 f 可能会使用许多变量,而不仅仅是 v1-v3,因此我不希望在调用函数时将它们全部命名。
编辑:我目前在 R 中的示例代码。在这个解决方案中,我传递了一个代词对象,我怀疑它是否合适。
d <- tibble(v1 = c(1,2,3), v2 = c(3,4,6), v3 = c(3,4,5))
f <- function(row){
if (row$v2 == 3) sum(something?) else 7
}
d %>% rowwise() %>% mutate(new_column = f(.data)) %>% ungroup()
edit2:预期输出。 (索引列不重要)
v1 v2 v3 new_col
0 1 3 3 4
1 2 4 4 7
2 3 6 5 7
注意:我不是在寻找这个特定问题的解决方案。我对将行传递给 R / dplyr 中的函数的一般方法感兴趣,就像 pandas 中的 apply() 一样。
将整行作为数据帧传递给函数的等效 dplyr 代码可能是:
library(tidyverse)
df <- tibble(v1 = c(1, 2, 3), v2 = c(4, 5, 6), v3 = c(7, 8, 9))
f <- function(row){
if (row$v2 == 3){
return(sum(row$v1, row$v3))
}else{
return(7)
}
}
df %>%
rowwise() %>%
do(row = as_data_frame(.)) %>%
mutate(new_col = f(row)) %>%
unnest()
输出:
# A tibble: 3 x 4
new_col v1 v2 v3
<dbl> <dbl> <dbl> <dbl>
1 4 1 3 3
2 7 2 4 4
3 7 3 6 5
如果您有一组完好无损的列,那么我建议您的函数只关注单个向量,而不是单行框架。
library(dplyr)
d <- tibble(v1 = c(1,2,3), v2 = c(3,4,6), v3 = c(3,4,5))
f <- function(v1, v2, v3) ifelse(v2 == 3, v1 + v3, 7)
d %>% rowwise() %>% mutate(new_column = f(v1, v2, v3)) %>% ungroup()
# # A tibble: 3 x 4
# v1 v2 v3 new_column
# <dbl> <dbl> <dbl> <dbl>
# 1 1 3 3 4
# 2 2 4 4 7
# 3 3 6 5 7
我用ifelse
防御,"in case"它曾用于组副行。如果您将函数定义为
f <- function(v1, v2, v3) if (v2 == 3) v1+v3 else 7
事实上,如果您的现实世界逻辑并不复杂,那么这不需要 rowwise()
,因此速度会快得多。 (但我不知道你真正的需求。)
选择:
d %>% mutate(new_column = purrr::pmap_dbl(list(v1,v2,v3), f))
df %>% mutate(new_col=with(.,case_when(v2 != 3 ~ 7,v2 == 3 ~ (v1 + v3))))
输出
v1 v2 v3 new_col
1 1 3 3 4
2 2 4 4 7
3 3 6 5 7