我有一系列日期:
date_rng <- seq( as.Date("2008-01-01"), as.Date("2008-12-31"), by="+1 day")
我有一些与问题相关的辅助功能,我会尝试将它们排除在外。
我从第一个日期开始并调用此函数:
# Function for getting weather table by airport code and date and return dataframe
get_table <- function(code, date){
adv <- sprintf(
"https://www.wunderground.com/history/airport/K%s/2008/%s/%s/DailyHistory.html",
code, month(date), day(date)
)
h <- adv %>% read_html()
t <- h%>%
html_nodes(xpath = '//*[@id="obsTable"]') %>%
html_table()
df <- data.frame(t)
return(df)
}
atl_weather <- get_table("ATL", date_rng[1])
现在我迭代其余的日期为每个日期创建一个新的df然后我尝试附加到原始日期:
# Loop through remaining dates and bind dfs
for(d in as.list(date_rng[2:4])){
rbind(atl_weather, get_table("ATL", d), d)
}
但绑定并没有发生,我在原始数据帧中留下了在for循环之前创建的范围中的第一个日期。
但这有效:
atl_weather <- get_table("ATL", date_rng[1])
new_df <- get_table("ATL", date_rng[2])
new_df <- scraped_data_formatter(new_df, date_rng[2])
rbind(atl_weather, new_df)
如何让rbind()在for循环中工作(这样我就可以迭代地构建数据帧以包含完整日期范围内的所有数据)?
答案 0 :(得分:5)
确实有效。问题是你丢弃了结果,因为你没有将rbind()
的输出分配给任何东西。
更改
rbind(atl_weather, get_table("ATL", d), d)
到这个
atl_weather <- rbind(atl_weather, get_table("ATL", d), d)
假设atl_weather
是您想要逐步添加的数据框。
那就是说,你不想要在R 中这样做;每次向对象添加列/行时,R都需要进行大量的数据复制。基本上,通过这种方式增量增长对象会带来很多开销,这样做可能会让代码陷入困境。
理想情况下,您首先要分配足够的空间(即足够的行,以便您可以在分配时i
索引new_atl_weather[i, ] <- c(....)
行。)
答案 1 :(得分:2)
我冒着偏离主题的风险(因为问题已经得到了正确回答),每当我被迫在for循环中构建数据帧时,给你我最喜欢的编程模式:
def get_event_stats(elengths, einds, *args, **kwargs):
master_list = []
# Unpack the recognized arguments (with default values), so kwargs left should be empty
avg = kwargs.pop('avg', False)
tot = kwargs.pop('tot', False)
# If any keywords left over, they're unrecognized, raise an error
if kwargs:
# Arbitrarily select alphabetically first unknown keyword arg
raise TypeError('get_event_stats() got an unexpected keyword argument {!r}'.format(min(kwargs)))
if avg:
for arg in args:
do stuff...
if tot:
for arg in args:
do stuff...
return master_list
当然,如果我有for (d in as.list(date_rng[2:4])){
if (exists("atl_weather")) {
atl_weather = rbind(atl_weather, get_table("ATL", d), d)
} else {
atl_weather = get_table("ATL", d)
}
}
中包含的功能,我会使用某种get_table
语句。但是当真实生活受阻并且for循环的内部过于复杂时,我通常会使用类似的模式将某些apply
对象分配给temp.data.frame
或者绑定到atl_weather
。以上:
if (exists("atl_weather")) rm(atl_weather) # in case I'm dynamically running code in chunks
for (d in as.list(date_rng[2:4])){
temp.df = ... # complicated stuff
if (exists("atl_weather")) {
atl_weather = rbind(atl_weather, temp.df)
} else {
atl_weather = temp.df
}
}