如何使 R 函数中的数据框可全局访问?
How do I make the dataframe within an R function globally accessible?
我使用 rvest
从歌词网站制作了这个用于提取歌词和专辑名称的 R 脚本。
songscrape <- function(y, a) {
url <- y
artist <- a
SongsListScrapper <- function(x) {
page <- x
songs <- page %>%
read_html() %>%
html_nodes('.listalbum-item') %>%
html_text() %>%
as.data.frame()
chart <- cbind(songs)
names(chart) <- c("Songs")
chart <- as.tibble(chart)
return(chart)
}
SongsList <- map_df(url, SongsListScrapper)
SongsList
SongsList %<>%
mutate(
Songs = as.character(Songs)
,Songs = gsub("[[:punct:]]", "", Songs)
,Songs = tolower(Songs)
,Songs = gsub(" ", "", Songs)
)
SongsList$Songs
#Scrape Lyrics
wipe_html <- function(str_html) {
gsub("<.*?>", "", str_html)
}
lyrics2 <- c()
albums2 <- c()
number <- 1
for(i in seq_along(SongsList$Songs)) {
for_url_name <- SongsList$Songs[i]
#clean name
for_url_name <- tolower(gsub("[[:punct:]]\s", "", for_url_name))
#create url
paste_url <- paste0("https://www.azlyrics.com/lyrics/", artist,"/", for_url_name, ".html")
#open connection to url
for_html_code <-read_html(paste_url)
for_lyrics <- html_node(for_html_code, xpath = "/html/body/div[2]/div/div[2]/div[5]")
for_albums <- html_node(for_html_code, xpath = "/html/body/div[2]/div/div[2]/div[11]/div[1]/b
")
for_lyrics <- wipe_html(for_lyrics)
for_albums <- wipe_html(for_albums)
lyrics2[number] <- for_lyrics
albums2[number] <- for_albums
number <- number +1
show(paste0(for_url_name, " scrape complete!"))
Sys.sleep(10)
}
songs2 <- cbind(lyrics2, albums2) %>% as.data.frame()
songs2$albums2 <- gsub("[[:punct:]]", "", songs$albums2)
}
函数 songscrape
有两个参数,y
和 a
,它们是 A-Z 歌词中的主要艺术家页面和 url 中的艺术家姓名(对于例如,songscrape("https://www.azlyrics.com/i/ironwine.html", "ironwine")
)
当我 运行 执行此操作时,我可以看到控制台中弹出状态消息,例如: "thenightdescending scrape complete!"
所以我知道该函数正确接收了参数,但我尝试中途停止它以进行检查如果一切正常,当我输入时:
View(lyrics2)
或 View(songs2)
,它给了我 Error: object 'songs2' not found
。
我以前没有使用过 R 函数,这是我第一次,但我猜这是因为这些对象的范围仅限于函数内。如何让这些对象在函数外部可访问并让函数将这些对象输出为数据帧?
我知道有两种方法可以实现这一点。首先是return一个列表。由于您可以将数据帧保存在列表中,因此这应该可行。
foo <- function(x, y){
i = x+1
k <- y+1
return(list(i, k))
}
df <- foo(1, 1)
另一种编码方式可能是:
foo <- function(x, y){
i = x+1
k <- y+1
df <- list()
df$first <- i
df$second <- k
return(df)
}
df <- foo(1, 1)
之后您可以通过从 returned 列表中提取值来创建单个数据帧:
df[1]
等
第二种方法是使用<<-
运算符,输出全局环境中的值。但我不推荐使用这种方法。通常你希望你的函数是一个封闭的环境,但它对调试很有用。总是 return 你想要的输出 return()
foo <- function(x, y){
i = x+1
k <<- y+1
}
foo(1, 1)
我使用 rvest
从歌词网站制作了这个用于提取歌词和专辑名称的 R 脚本。
songscrape <- function(y, a) {
url <- y
artist <- a
SongsListScrapper <- function(x) {
page <- x
songs <- page %>%
read_html() %>%
html_nodes('.listalbum-item') %>%
html_text() %>%
as.data.frame()
chart <- cbind(songs)
names(chart) <- c("Songs")
chart <- as.tibble(chart)
return(chart)
}
SongsList <- map_df(url, SongsListScrapper)
SongsList
SongsList %<>%
mutate(
Songs = as.character(Songs)
,Songs = gsub("[[:punct:]]", "", Songs)
,Songs = tolower(Songs)
,Songs = gsub(" ", "", Songs)
)
SongsList$Songs
#Scrape Lyrics
wipe_html <- function(str_html) {
gsub("<.*?>", "", str_html)
}
lyrics2 <- c()
albums2 <- c()
number <- 1
for(i in seq_along(SongsList$Songs)) {
for_url_name <- SongsList$Songs[i]
#clean name
for_url_name <- tolower(gsub("[[:punct:]]\s", "", for_url_name))
#create url
paste_url <- paste0("https://www.azlyrics.com/lyrics/", artist,"/", for_url_name, ".html")
#open connection to url
for_html_code <-read_html(paste_url)
for_lyrics <- html_node(for_html_code, xpath = "/html/body/div[2]/div/div[2]/div[5]")
for_albums <- html_node(for_html_code, xpath = "/html/body/div[2]/div/div[2]/div[11]/div[1]/b
")
for_lyrics <- wipe_html(for_lyrics)
for_albums <- wipe_html(for_albums)
lyrics2[number] <- for_lyrics
albums2[number] <- for_albums
number <- number +1
show(paste0(for_url_name, " scrape complete!"))
Sys.sleep(10)
}
songs2 <- cbind(lyrics2, albums2) %>% as.data.frame()
songs2$albums2 <- gsub("[[:punct:]]", "", songs$albums2)
}
函数 songscrape
有两个参数,y
和 a
,它们是 A-Z 歌词中的主要艺术家页面和 url 中的艺术家姓名(对于例如,songscrape("https://www.azlyrics.com/i/ironwine.html", "ironwine")
)
当我 运行 执行此操作时,我可以看到控制台中弹出状态消息,例如: "thenightdescending scrape complete!"
所以我知道该函数正确接收了参数,但我尝试中途停止它以进行检查如果一切正常,当我输入时:
View(lyrics2)
或 View(songs2)
,它给了我 Error: object 'songs2' not found
。
我以前没有使用过 R 函数,这是我第一次,但我猜这是因为这些对象的范围仅限于函数内。如何让这些对象在函数外部可访问并让函数将这些对象输出为数据帧?
我知道有两种方法可以实现这一点。首先是return一个列表。由于您可以将数据帧保存在列表中,因此这应该可行。
foo <- function(x, y){
i = x+1
k <- y+1
return(list(i, k))
}
df <- foo(1, 1)
另一种编码方式可能是:
foo <- function(x, y){
i = x+1
k <- y+1
df <- list()
df$first <- i
df$second <- k
return(df)
}
df <- foo(1, 1)
之后您可以通过从 returned 列表中提取值来创建单个数据帧:
df[1]
等
第二种方法是使用<<-
运算符,输出全局环境中的值。但我不推荐使用这种方法。通常你希望你的函数是一个封闭的环境,但它对调试很有用。总是 return 你想要的输出 return()
foo <- function(x, y){
i = x+1
k <<- y+1
}
foo(1, 1)