R написание функции, чтобы избежать цикла - PullRequest
0 голосов
/ 28 января 2020

Привет! Я пытаюсь узнать, как избежать циклов в моих кодах.

У меня есть пример данных:

options(warn=-1) #Turning warnings off here
Company=c("A","C","B","B","A","C","C","A","B","C","B","A")
CityID=as.character(c(1,1,1,2,2,2,3,3,3,4,4,4))
Value=c(120.5,123,125,122.5,122.1,121.7,123.2,123.7,120.7,122.3,120.1,122)
Sales=c(1,1,0,0,0,1,1,0,1,0,1,0)
df=data.frame(Company,CityID,Sales,Value)
df$new_value=0

Я также создал пользовательскую функцию (просто Пример только для тестирования), как показано ниже.

funcCity12 = function(data){
  data_new=data[which(data$CityID == '1'|data$CityID == '2'),]
  for (i in 1:nrow(data_new)){
    data_company=df[(df$Company)==data_new[i,'Company'] & !df$CityID==1 & !df$CityID==2,]
    data_new[i,'new_value'] = max(data_company[data_company$Sales==1,]$Value) #Note we take the maximum value here
  }
  data_new
}

df2=funcCity12(data=df) # obtaining the result here

Теперь я пытаюсь написать функцию, чтобы избежать для l oop в предыдущей функции.

funcCity12_no_loop = function(x,df){
  data_company=df[(df$Company)==x[,'Company'] & !df$CityID==1 & !df$CityID==2,]
  x[,'new_value'] = max(data_company[data_company$Sales==1,]$Value) #Note we take the maximum value here
  x
}

funcCity12_no_loop(x=df[1,],df=df) #Output for the first row of df1

Это кажется работать при вводе строк по отдельности. Я застрял в том, как запустить эту функцию для всех строк информационного кадра. Я не уверен, что 2-я функция требует больше изменений для этой цели. Любая помощь приветствуется. Заранее спасибо.

PS Для второй функции моей первоначальной реакцией было создание для l oop и l oop посредством наблюдений, но это разрушает всю цель.

РЕДАКТИРОВАТЬ

Это основано на ответе @ eonurk

zz=apply(df,1, function(x){ 
  data_company=df[(df$Company)==x[1] & !df$CityID==1 & !df$CityID==2,]
  x[5] = max(data_company[data_company$Sales==1,]$Value) #Note we take the maximum value here
  x
})

Вывод показан ниже:

enter image description here

Ответы [ 2 ]

1 голос
/ 28 января 2020

Вы можете использовать функцию apply, чтобы охватить каждое отдельное наблюдение вашего фрейма данных.

Например, вы можете без всяких причин умножать столбцы Values ​​и Sales со следующими значениями:

apply(df,1, function(x){ as.numeric(x["Sales"])*as.numeric(x["Value"])})

Редактировать:

Теперь вам просто нужно использовать dplyr пакет

zz=apply(df,1, function(x){ 
  data_company=df[(df$Company)==x[1] & !df$CityID==1 & !df$CityID==2,]
  x[5] = max(data_company[data_company$Sales==1,]$Value) #Note we take the maximum value here
  x
}) %>% as.data.frame %>% t
0 голосов
/ 29 января 2020

Вот один из способов без всех oop. Сначала мы фильтруем по вашим критериям, затем группируем по компании и рассчитываем максимальное значение, затем присоединяем фрейм данных к исходному набору данных (также фильтруемому по вашим критериям). Я не сделал это функцией, но все строительные блоки там.

library(tidyverse)

list(
df %>%
  filter(CityID %in% 1:2) %>%
  select(-new_value),
df %>%
  filter(! CityID %in% 1:2 & Sales == 1) %>%
  group_by(Company) %>%
  summarise(new_value = max(Value))
) %>%
  reduce(full_join, by = "Company")
#>   Company CityID Sales Value new_value
#> 1       A      1     1 120.5        NA
#> 2       C      1     1 123.0     123.2
#> 3       B      1     0 125.0     120.7
#> 4       B      2     0 122.5     120.7
#> 5       A      2     0 122.1        NA
#> 6       C      2     1 121.7     123.2
...