R: Проблема с использованием ifelse для запуска нескольких логических тестов во фреймах данных для создания нового столбца

#r #dataframe #if-statement #match

#r #фрейм данных #if-statement #совпадение

Вопрос:

Я пытаюсь, используя данные бейсбольной игры retrosheet, присвоить имя кэтчеру для любого заданного броска, сделанного в эпоху pitfx. Я использовал ifelse для запуска серии тестов, чтобы найти стартовый ловец. Код и ошибки приведены ниже — также я намерен после того, как это заработает, вместо вывода «нет» в случае сбоя, вложить в это аналогичные тесты ifelse, пока я не перейду с HmBat1Pos на HmBat9Pos … и т.д.

 atbat$starting_catcher_retro = ifelse(((atbat$date = retro_games$Date)                                       
                         amp; (atbat$pitcher_name = retro_games$HmStPchNm) 
                         amp; (atbat$num = 1) 
                         amp; (atbat$inning_side = "top")
                         amp; (retro_games$HmBat1Pos = 2)), 
                         retro_games$HmBat1ID, "no")
  

ошибки

 Error in `$<-.data.frame`(`*tmp*`, date, value = c(13963, 13964, 13968,  : 
  replacement has 26726 rows, data has 2146373
  

Затем я попытался удалить часть кода, проверяющего дату, и все равно получил ошибки. Поэтому я запустил это вместо

 atbat$starting_catcher_retro = ifelse(((atbat$num = 1) 
                                         amp; (atbat$inning_side = "top")
                                         amp;(retro_games$HmBat1Pos = 2)), 
                                         retro_games$HmBat1ID, "no")
  

и получил эти другие ошибки

 Error in (atbat$num = 1) amp; (atbat$inning_side = "top") : 
  operations are possible only for numeric, logical or complex types
  

ответ на комментарии

это был код, который я добавил, и возвращенная ошибка

 > merged_df <- merge(atbat, retro_games,
                     by.x = c("date", "pitcher_name"),
                     by.y = c("Date", "HmStPchNm"), all.x = FALSE)
> 
> merged_df$starting_catcher_retro = with(merged_df, 
                                          ifelse((num == 1) 
                                                 amp; (inning_side == "top")
                                                 amp; (HmBat3Pos == 2), 
                                                 HmBat3ID, "no"))
> 
> atbat$starting_catcher_retro <- merged_df$starting_catcher_retro[match(merged_df$unique_id, atbat$unique_id)]
Error in `$<-.data.frame`(`*tmp*`, starting_catcher_retro, value = c("no",  : 
  replacement has 566448 rows, data has 2146373
  

Я также попытался применить подход, отличный от описанного выше, который основан на идее, которая пришла мне в голову — ниже приведен этот код и возвращенные ошибки, в которых все выглядит так, как будто должно работать, но даже не создан новый столбец

 atbat$starting_catcher_retro = ifelse(((retro_games$Date %in% atbat$date) 
                                       amp; (retro_games$HmStPchNm %in% atbat$pitcher_name) 
                                       amp; (atbat$inning_side == "top")
                                       amp; (retro_games$HmBat1Pos == 2)), 
                                      retro_games$HmBat1ID, 
                                      ifelse(((retro_games$Date %in% atbat$date) 
                                              amp; (retro_games$HmStPchNm %in% atbat$pitcher_name) 
                                              amp; (atbat$inning_side == "top")
                                              amp; (retro_games$HmBat2Pos == 2)), 
                                             retro_games$HmBat2ID, 
                                             ifelse(((retro_games$Date %in% atbat$date) 
                                                     amp; (retro_games$HmStPchNm %in% atbat$pitcher_name) 
                                                     amp; (atbat$inning_side == "top")
                                                     amp; (retro_games$HmBat3Pos == 2)), 
                                                    retro_games$HmBat3ID, 
                                                    ifelse(((retro_games$Date %in% atbat$date) 
                                                            amp; (retro_games$HmStPchNm %in% atbat$pitcher_name) 
                                                            amp; (atbat$inning_side == "top")
                                                            amp; (retro_games$HmBat4Pos == 2)), 
                                                           retro_games$HmBat4ID, 
                                                           ifelse(((retro_games$Date %in% atbat$date) 
                                                                   amp; (retro_games$HmStPchNm %in% atbat$pitcher_name) 
                                                                   amp; (atbat$inning_side == "top")
                                                                   amp; (retro_games$HmBat5Pos == 2)), 
                                                                  retro_games$HmBat5ID, 
                                                                  ifelse(((retro_games$Date %in% atbat$date) 
                                                                          amp; (retro_games$HmStPchNm %in% atbat$pitcher_name) 
                                                                          amp; (atbat$inning_side == "top")
                                                                          amp; (retro_games$HmBat6Pos == 2)), 
                                                                         retro_games$HmBat6ID, 
                                                                         ifelse(((retro_games$Date %in% atbat$date) 
                                                                                 amp; (retro_games$HmStPchNm %in% atbat$pitcher_name) 
                                                                                 amp; (atbat$inning_side == "top")
                                                                                 amp; (retro_games$HmBat7Pos == 2)), 
                                                                                retro_games$HmBat7ID, 
                                                                                ifelse(((retro_games$Date %in% atbat$date) 
                                                                                        amp; (retro_games$HmStPchNm %in% atbat$pitcher_name) 
                                                                                        amp; (atbat$inning_side == "top")
                                                                                        amp; (retro_games$HmBat8Pos == 2)), 
                                                                                       retro_games$HmBat8ID, 
                                                                                       ifelse(((retro_games$Date %in% atbat$date) 
                                                                                               amp; (retro_games$HmStPchNm %in% atbat$pitcher_name) 
                                                                                               amp; (atbat$inning_side == "top")
                                                                                               amp; (retro_games$HmBat9Pos == 2)), 
                                                                                              retro_games$HmBat9ID, 
                                                                                              ifelse(((retro_games$Date %in% atbat$date) 
                                                                                                      amp; (retro_games$VisStPchNm %in% atbat$pitcher_name) 
                                                                                                      amp; (atbat$inning_side == "bottom")
                                                                                                      amp; (retro_games$VisBat1Pos == 2)), 
                                                                                                     retro_games$VisBat1ID, 
                                                                                                     ifelse(((retro_games$Date %in% atbat$date) 
                                                                                                             amp; (retro_games$VisStPchNm %in% atbat$pitcher_name) 
                                                                                                             amp; (atbat$inning_side == "bottom")
                                                                                                             amp; (retro_games$VisBat2Pos == 2)), 
                                                                                                            retro_games$VisBat12D, 
                                                                                                            ifelse(((retro_games$Date %in% atbat$date) 
                                                                                                                    amp; (retro_games$VisStPchNm %in% atbat$pitcher_name) 
                                                                                                                    amp; (atbat$inning_side == "bottom")
                                                                                                                    amp; (retro_games$VisBat3Pos == 2)), 
                                                                                                                   retro_games$VisBat3ID, 
                                                                                                                   ifelse(((retro_games$Date %in% atbat$date) 
                                                                                                                           amp; (retro_games$VisStPchNm %in% atbat$pitcher_name) 
                                                                                                                           amp; (atbat$inning_side == "bottom")
                                                                                                                           amp; (retro_games$VisBat4Pos == 2)), 
                                                                                                                          retro_games$VisBat4ID, 
                                                                                                                          ifelse(((retro_games$Date %in% atbat$date) 
                                                                                                                                  amp; (retro_games$VisStPchNm %in% atbat$pitcher_name) 
                                                                                                                                  amp; (atbat$inning_side == "bottom")
                                                                                                                                  amp; (retro_games$VisBat5Pos == 2)), 
                                                                                                                                 retro_games$VisBat5ID, 
                                                                                                                                 ifelse(((retro_games$Date %in% atbat$date) 
                                                                                                                                         amp; (retro_games$VisStPchNm %in% atbat$pitcher_name) 
                                                                                                                                         amp; (atbat$inning_side == "bottom")
                                                                                                                                         amp; (retro_games$VisBat6Pos == 2)), 
                                                                                                                                        retro_games$VisBat6ID, 
                                                                                                                                        ifelse(((retro_games$Date %in% atbat$date) 
                                                                                                                                                amp; (retro_games$VisStPchNm %in% atbat$pitcher_name) 
                                                                                                                                                amp; (atbat$inning_side == "bottom")
                                                                                                                                                amp; (retro_games$VisBat7Pos == 2)), 
                                                                                                                                               retro_games$VisBat7ID, 
                                                                                                                                               ifelse(((retro_games$Date %in% atbat$date) 
                                                                                                                                                       amp; (retro_games$VisStPchNm %in% atbat$pitcher_name) 
                                                                                                                                                       amp; (atbat$inning_side == "bottom")
                                                                                                                                                       amp; (retro_games$VisBat8Pos == 2)), 
                                                                                                                                                      retro_games$VisBat8ID, 
                                                                                                                                                      ifelse(((retro_games$Date %in% atbat$date) 
                                                                                                                                                              amp; (retro_games$VisStPchNm %in% atbat$pitcher_name) 
amp; (atbat$inning_side == "bottom")
                                                                                                                                                              amp; (retro_games$VisBat9Pos == 2)), 
                                                                                                                                                             retro_games$VisBat9ID, ""))))))))))))))))))

  

и ошибка

 Error in ans[test amp; ok] <- rep(yes, length.out = length(ans))[test amp; ok] : 
  replacement has length zero
In addition: There were 23 warnings (use warnings() to see them)
> warnings()
Warning messages:
1: In (retro_games$Date %in% atbat$date) amp; (retro_games$HmStPchNm %in%  ... :
  longer object length is not a multiple of shorter object length
2: In (retro_games$Date %in% atbat$date) amp; (retro_games$HmStPchNm %in%  ... :
  longer object length is not a multiple of shorter object length
3: In (retro_games$Date %in% atbat$date) amp; (retro_games$HmStPchNm %in%  ... :
  longer object length is not a multiple of shorter object length
4: In (retro_games$Date %in% atbat$date) amp; (retro_games$HmStPchNm %in%  ... :
  longer object length is not a multiple of shorter object length
5: In (retro_games$Date %in% atbat$date) amp; (retro_games$HmStPchNm %in%  ... :
  longer object length is not a multiple of shorter object length
6: In (retro_games$Date %in% atbat$date) amp; (retro_games$HmStPchNm %in%  ... :
  longer object length is not a multiple of shorter object length
7: In (retro_games$Date %in% atbat$date) amp; (retro_games$HmStPchNm %in%  ... :
  longer object length is not a multiple of shorter object length
8: In (retro_games$Date %in% atbat$date) amp; (retro_games$HmStPchNm %in%  ... :
  longer object length is not a multiple of shorter object length
9: In (retro_games$Date %in% atbat$date) amp; (retro_games$HmStPchNm %in%  ... :
  longer object length is not a multiple of shorter object length
10: In (retro_games$Date %in% atbat$date) amp; (retro_games$HmStPchNm %in%  ... :
  longer object length is not a multiple of shorter object length
11: In (retro_games$Date %in% atbat$date) amp; (retro_games$HmStPchNm %in%  ... :
  longer object length is not a multiple of shorter object length
12: In (retro_games$Date %in% atbat$date) amp; (retro_games$HmStPchNm %in%  ... :
  longer object length is not a multiple of shorter object length
13: In (retro_games$Date %in% atbat$date) amp; (retro_games$HmStPchNm %in%  ... :
  longer object length is not a multiple of shorter object length
14: In (retro_games$Date %in% atbat$date) amp; (retro_games$HmStPchNm %in%  ... :
  longer object length is not a multiple of shorter object length
15: In (retro_games$Date %in% atbat$date) amp; (retro_games$HmStPchNm %in%  ... :
  longer object length is not a multiple of shorter object length
16: In (retro_games$Date %in% atbat$date) amp; (retro_games$HmStPchNm %in%  ... :
  longer object length is not a multiple of shorter object length
17: In (retro_games$Date %in% atbat$date) amp; (retro_games$HmStPchNm %in%  ... :
  longer object length is not a multiple of shorter object length
18: In (retro_games$Date %in% atbat$date) amp; (retro_games$HmStPchNm %in%  ... :
  longer object length is not a multiple of shorter object length
19: In (retro_games$Date %in% atbat$date) amp; (retro_games$VisStPchNm %in%  ... :
  longer object length is not a multiple of shorter object length
20: In (retro_games$Date %in% atbat$date) amp; (retro_games$VisStPchNm %in%  ... :
  longer object length is not a multiple of shorter object length
21: In (retro_games$Date %in% atbat$date) amp; (retro_games$VisStPchNm %in%  ... :
  longer object length is not a multiple of shorter object length
22: In (retro_games$Date %in% atbat$date) amp; (retro_games$VisStPchNm %in%  ... :
  longer object length is not a multiple of shorter object length
23: In rep(yes, length.out = length(ans)) :
  'x' is NULL so the result will be NULL
  

правка2

выборка из обоих фреймов данных из первых 15 строк была слишком длинной для включения, вот ее фрагмент — https://pastebin.com/kTVEgdRs

Комментарии:

1. Ваш логический тест должен использовать == вместо = , верно? это помогает?

2. @liuminzhao Моя ошибка новичка, ты прав, это помогает… единственная проблема сейчас в том, что весь столбец заполнен только «no», даже когда я запускаю его для всей линейки…

Ответ №1:

Обычно ifelse выполняется в одном фрейме данных, обеспечивая равное количество строк не во всех наборах данных. Сначала рассмотрите возможность объединения, а затем запустите ifelse . Ниже выполняется объединение по левому краю, сохраняя все строки в atbat.

 merged_df <- merge(atbat, retro_games,
                   by.x = c("date", "pitcher_name"),
                   by.y = c("Date", "HmStPchNm"), all.x = TRUE)

merged_df$starting_catcher_retro = with(merged_df, 
                                     ifelse((num == 1) 
                                             amp; (inning_side == "top")
                                             amp; (HmBat1Pos == 2), 
                                             HmBat1ID, "no")
                                     )
  

Комментарии:

1. Это выглядит намного проще, чем то, что я пытался, но при использовании этого я столкнулся с двумя проблемами — первая заключается в том, что при ручной перекрестной проверке нескольких ловушек, просматривая atbat, а затем просматривая retrosheet, я получал неправильные идентификаторы, где некоторые были игроками, которые вообще не ловят, вторая — ошибка в чем-то, что я добавил, чтобы переместить те же данные из объединенного фрейма данных в фрейм данных atbat — все выше в моем отредактированном исходном сообщении.

2. Глядя на вашу merge попытку, вы повторяете ту же ошибку назначения ifelse во фреймах данных. Не делайте этого. И merge может даже сократить вашу вложенность ifelse . Пожалуйста dput , небольшой пример обоих фреймов данных и желаемого результата.

3. Вот ссылка pasetbin на dput первых 15 строк обоих — pastebin.com/kTVEgdRs — что касается моего желаемого результата, я просто хочу столбец в atbat с именем кетчера только в том, что будет первым на bat, потому что тогда я могу установить этот кетчер для всей игры, используя комбинацию gamelink и какой стороны подачи (верхней или нижней). У меня есть отдельный файл от pitchfx, в котором есть защитные замены, которые я могу затем использовать для обновления имени ловца для каждой игры в зависимости от подачи и от того, было ли на самом деле изменение, как только я узнаю стартера.

4. В вашей ссылке есть только dput of atbat .

5. Я также не совсем понимаю, что вы имеете в виду, говоря, что я повторяю ту же ошибку