如何创建一个自定义函数来使用purrr或lapply



我是一个初学者,想知道如何不剪切和粘贴60行代码。这是我的数据帧

df <- data.frame(
stringsAsFactors = FALSE,
id = c(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L),
people = c("marge","homer","homer",
"homer","marge","bart","homer","homer","marge")
)

我试着写一个函数,这样我就可以指定输入,使这更容易。实际上,我希望x是一个向量,但我甚至无法将其用于单个观测。

lisaList <- function (x) {
df[df$id==x, "people"] <- "lisa" 
}
#vector with the list of id's I want to change to "lisa"
myList=c(1,2,3)

我尝试过的不起作用的东西

lisaList(myList)

这不起作用

lisaL <- function (x) {
if(df$id==x) df[df$id==x, "people"] <- "lisa" }
lisaL(myList)

我也试着用mutate写一些东西,然后用purrr,但我也不明白。

我希望在";id";其=1、2或3被改变为"0";lisa";所以我最终得到了这个

df <- data.frame(
stringsAsFactors = FALSE,
id = c(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L),
people = c("lisa","lisa","lisa",
"homer","marge","bart","homer","homer","marge")
)

谢谢。

跟进我的原始问题

谢谢你们两个!这些答案帮助我跨过了一道障碍。现在,我还有另外两个问题,通过在我的df中添加另一列来扩展这个函数。后续问题1现在我希望能够输入需要更改的观察结果。

df <- data.frame(
stringsAsFactors = FALSE,
id = c(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L),
people = c("bart","lisa","lisa",
"homer","marge","bart","homer","homer","marge"),
pets = c("dog","wolf","horse",
"bat","mouse","mole","gopher","bat","bat")
)
# new function
list3 <- function(dat, x, y) {
dat %>%
mutate(people = replace(people,  id %in% x, y))
}
myList=c(3,4,5)
list3 (df, myList, 'cat')

这可以正常工作,但我的功能中是否有可以更改的内容,这样用户就不需要用"输入观察结果了?

我能够实现一些接近我想要的东西,但这需要创建一个新的列表。

otherList <- c("ground hog")
list3 (df, myList, otherList)

后续问题2现在我希望用户能够输入要更改的列,而不是在函数中硬编码列名。我一直在试图弄清楚这一点(这就是为什么我认为我可能会尝试在函数中使用mutate的替代方法(,但现在我觉得我已经很接近了,我想看看如何做到这一点。

所以第一次尝试没有成功。

list4 <- function(dat, x, y, z) {
dat %>%
mutate(z = replace(z,  id %in% x, y))
}
mycol <- c('pets')
list4(df, myList, 'birds', mycol)

但这并没有奏效。

list4 <- function(dat, x, y, z) {
dat %>%
mutate((enquo(z)) = replace( (!!z),  id %in% x, y))
}
mycol <- c('pets')
list4(df, myList, 'birds', mycol)

以及许多其他版本尝试使用{{}}或指定enquo((和!!

你能帮我弄清楚如何输入列名吗?再次感谢你们两位的初步帮助!

我建议在dplyr管道中使用ifelse

lisaList <- function (x) {
df%>%
mutate(people=ifelse(id %in% x,"lisa", people))
}
myList=c(1,2,3)
lisaList(myList)
id people
1  1   lisa
2  2   lisa
3  3   lisa
4  4  homer
5  5  marge
6  6   bart
7  7  homer
8  8  homer
9  9  marge

关于第三个问题,可以使用acrossmutate中指定变量名。为了提高可读性,我已经将参数重命名为您的函数:

list3 <- function(dat, rowindex, replacestring, colnamevar) {
dat %>%
mutate(across(colnamevar, ~ifelse(id %in% rowindex, replacestring, .)))
}
list3(df, myList, 'birds', mycol)
id people   pets
1  1   bart    dog
2  2   lisa   wolf
3  3   lisa  birds
4  4  homer  birds
5  5  marge  birds
6  6   bart   mole

最后,不知道有什么方法可以让R将未引用的文本识别为字符串而不是变量。

我们可以使用%in%而不是==

df$people[df$id %in% 1:3] <- "lisa"

因此,功能将是

lisaL <- function (dat, x) {
dat$people[dat$id %in% x] <- "lisa" 
dat
}

lisaL(df, myList)
#  id people
#1  1   lisa
#2  2   lisa
#3  3   lisa
#4  4  homer
#5  5  marge
#6  6   bart
#7  7  homer
#8  8  homer
#9  9  marge

或使用replacemutate

library(dplyr)
lisaList2 <- function(dat, x) {
dat %>%
mutate(people = replace(people,  id %in% x, 'lisa'))
}

如果我们想使用==,那么一个选项是用lapplyfor循环"myList",创建一个逻辑向量,用|将其Reduce转换为单个逻辑向量,并分配

listList3 <- function(dat, x) {
dat$people[Reduce(`|`, lapply(x, function(u) dat$id == u))] <- 'lisa'
dat
}
listList3(df, myList)

最新更新