[R] for loop is looping only once

Duncan Murdoch murdoch.duncan at gmail.com
Thu Nov 17 12:44:20 CET 2016


On 17/11/2016 6:26 AM, Ulrik Stervbo wrote:
> Hi Georg,
>
> Your for loop iterates over just one value, to get it to work as you intend
> use for(item in 1:length(kpis)){}

That usually works, but fails often enough that we recommend using

for (item in seq_along(kpis)) {}

(The failures happen if length(kpis) is zero.  1:0 is a length 2 vector, 
not a length 0 one.)

Duncan Murdoch

>
> HTH
> Ulrik
>
> On Thu, 17 Nov 2016 at 12:18 <G.Maubach at weinwolf.de> wrote:
>
>> Hi All,
>>
>> I need to execute a loop on variables to compute several KPIs.
>> Unfortunately the for loop is executed only once for the last KPI given.
>> The code below illustrates my current solution but is not completely
>> necessary to spot the problem. I just give an idea what I am doing
>> overall. Looks much but isn't if copied and run in RStudio. The problem
>> occurs in function f_create_kpi_table() in lines 150 to 157:
>>
>>   for (item in length(kpis))  # This loop runs only once!
>>   {
>>     print(kpis[[item]])
>>     ds_kpi <- f_compute_kpi(
>>       years    = years,
>>       kpi      = kpis[[item]],
>>       kpi_base = kpi_bases[[item]])
>>     print(ds_kpi)
>>
>> Here is the complete example code with example data:
>>
>> - cut --
>> dataset <-
>>   structure(
>>     list(
>>       to_2012 = c(
>>         85,
>>         822,
>>         891,
>>         700,
>>         386,
>>         127,
>>         938,
>>         381,
>>         871,
>>         254,
>>         793,
>>         0,
>>         934,
>>         217,
>>         163,
>>         755,
>>         607,
>>         794,
>>         477
>>       ),
>>       to_2013 = c(
>>         289,
>>         0,
>>         963,
>>         243,
>>         608,
>>         47,
>>         0,
>>         941,
>>         998,
>>         775,
>>         326,
>>         0,
>>         0,
>>         470,
>>         248,
>>         439,
>>         212,
>>         0,
>>         0
>>       ),
>>       to_2014 = c(0, 0, 71, 0, 0, 434, 0, 282, 0,
>>                   0, 405, 0, 0, 642, 0, 0, 0, 47, 299),
>>       to_2015 = c(
>>         705,
>>         134,
>>         659,
>>         0,
>>         609,
>>         807,
>>         783,
>>         0,
>>         0,
>>         304,
>>         141,
>>         500,
>>         0,
>>         0,
>>         764,
>>         790,
>>         851,
>>         0,
>>         802
>>       ),
>>       kpi1_2013 = c(0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0,
>>                     0, 0, 0, 1, 1),
>>       kpi1_2014 = c(1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0,
>>                     1, 1, 0, 1, 1, 1, 0, 0),
>>       kpi1_2015 = c(0, 0, 0, 1, 0, 0, 0, 1,
>>                     1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0),
>>       kpi1_2016 = c(0, 1, 0, 1, 0,
>>                     1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1),
>>       kpi2_2013 = c(1, 0,
>>                     1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0),
>>       kpi2_2014 = c(0,
>>                     0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1),
>>       kpi2_2015 = c(1,
>>                     1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1),
>>       kpi2_2016 = c(1,
>>                     0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0)
>>     ),
>>     .Names = c(
>>       "to_2012",
>>       "to_2013",
>>       "to_2014",
>>       "to_2015",
>>       "kpi1_2013",
>>       "kpi1_2014",
>>       "kpi1_2015",
>>       "kpi1_2016",
>>       "kpi2_2013",
>>       "kpi2_2014",
>>       "kpi2_2015",
>>       "kpi2_2016"
>>     ),
>>     row.names = c(NA, 19L),
>>     class = "data.frame"
>>   )
>>
>> f_compute_kpi <- function(
>>   years,
>>   kpi,
>>   kpi_base)
>> {
>>   print(years)
>>   print(kpi)
>>   print(kpi_base)
>>
>>   ds_result <- data.frame()
>>
>>   for (year in years) {
>>     current_year  <- year
>>     previous_year <- year - 1
>>     result <- sum(dataset[dataset[[paste0(kpi,
>>                                           "_",
>>                                           current_year)]] == 1 ,
>>                           paste0(kpi_base,
>>                                  "_", previous_year)],
>>                   na.rm = TRUE)
>>     ds_result <- rbind(ds_result, result)
>>   }
>>
>>   ds_result           <- t(ds_result)
>>   rownames(ds_result) <- kpi
>>   colnames(ds_result) <- years
>>
>>   invisible(ds_result)
>> }
>>
>> f_create_kpi_table <- function(
>>   years,
>>   kpis,
>>   kpi_bases)
>> {
>>   print(length(kpis))
>>
>> #-- Problematic loop --
>>   for (item in length(kpis))  # This loop runs only once!
>>   {
>>     print(kpis[[item]])
>>     ds_kpi <- f_compute_kpi(
>>       years    = years,
>>       kpi      = kpis[[item]],
>>       kpi_base = kpi_bases[[item]])
>>     print(ds_kpi)
>>   }
>>   # This for loop is executed only once for kpi2 instead of
>>   # as many times as given kpis in length(kpis), i. e.
>>   # kpi1 AND kpi2.
>>   # Why?
>>   # What do I do wrong?
>> }
>> -- cut --
>>
>> What do I need to change to get the loop work correctly and loop over two
>> elements instead of one when calling the function
>>
>> f_create_kpi_table(years = 2013:2016, kpis = c("kpi1", "kpi2"), kpi_bases
>> = c("to", "to"))
>>
>> Kind regards
>>
>> Georg
>>
>> ______________________________________________
>> R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see
>> https://stat.ethz.ch/mailman/listinfo/r-help
>> PLEASE do read the posting guide
>> http://www.R-project.org/posting-guide.html
>> and provide commented, minimal, self-contained, reproducible code.
>>
>
> 	[[alternative HTML version deleted]]
>
> ______________________________________________
> R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.
>



More information about the R-help mailing list