Итерация операции со столбцами в кадре данных с использованием цикла - PullRequest
0 голосов
/ 16 апреля 2019

У меня есть фрейм данных с именами столбцов, которые включают указатели недели и года в формате "W1_2019" плюс другой текст. Полный фрейм данных содержит 52 столбца по 5 недель. Моя цель состоит в том, чтобы взять следующий код, который в точности соответствует тому, что я хочу сделать в течение недель 1 и 2, и поместить его в цикл для x = 1–52, чтобы мне не приходилось использовать 52 раза ту же половину дюжина строк.

eidsr <- dget(file="test1.txt")

mode_xmt <- data.frame(District=eidsr$district) #Initializes dataframe mode_xmt with only 1 column containing District names

wtmp <- select(eidsr, contains("W1_2019"))
wtmp$mode <- "NoRep"
wtmp$mode[wtmp$W1_2019_EIDSR_Total_Malaria_cases>0] <- "Report"
wtmp$mode[wtmp$`W1_2019_EIDSR-Mobile_SMS`==1] <- "Mobile_SMS"
wtmp$mode[wtmp$`W1_2019_EIDSR-Mobile_Internet`==1] <- "Mobile_Internet"

#At this point the dataframe wtmp looks like the example below.

mode_xmt$`2019_W1` <- wtmp$mode #Appends ONLY the W1_2019 column to mode_xmt
rm(wtmp)

wtmp <- select(eidsr, contains("W2_2019"))
wtmp$mode <- "NoRep"
wtmp$mode[wtmp$W2_2019_EIDSR_Total_Malaria_cases>0] <- "Report"
wtmp$mode[wtmp$`W2_2019_EIDSR-Mobile_SMS`==1] <- "Mobile_SMS"
wtmp$mode[wtmp$`W2_2019_EIDSR-Mobile_Internet`==1] <- "Mobile_Internet"

mode_xmt$`2019_W2` <- wtmp$mode
rm(wtmp)

В конце каждой операции мои рабочие данные следующие. Dataframe wtmp выглядит так:

   `W1_2019_EIDSR-Timely_~ W1_2019_EIDSR_Total_Mala~ W1_2019_EIDSR_Date_R~ `W1_2019_EIDSR-Mobile_~ `W1_2019_EIDSR-Mobi~ mode 
                     <dbl>                     <dbl> <chr>                                   <dbl>                <dbl> <chr>
 1                      NA                         0 NA                                         NA                   NA NoRep
 2                      NA                        NA NA                                         NA                   NA NoRep
 3                      NA                        51 NA                                         NA                   NA Repo~
 4                      NA                        NA NA                                         NA                   NA NoRep
 5                      NA                        64 NA                                         NA                   NA Repo~
 6                      NA                        86 NA                                         NA                   NA Repo~
 7                      NA                        92 NA                                         NA                   NA Repo~
 8                      NA                        47 NA                                         NA                   NA Repo~
 9                      NA                        46 NA                                         NA                   NA Repo~
10                      NA                        35 NA                                         NA                   NA Repo~

mode_xmt с добавленным новым столбцом выглядит следующим образом:

   District 2019_W01
1        Bo    NoRep
2        Bo    NoRep
3        Bo   Report
4        Bo    NoRep
5        Bo   Report
6        Bo   Report
7        Bo   Report
8        Bo   Report
9        Bo   Report
10       Bo   Report

И после того, как я выполнил вторую итерацию для W2, mode_xmt выглядит так:

   District 2019_W01 2019_W02
1        Bo    NoRep   Report
2        Bo    NoRep    NoRep
3        Bo   Report   Report
4        Bo    NoRep    NoRep
5        Bo   Report   Report
6        Bo   Report   Report
7        Bo   Report   Report
8        Bo   Report   Report
9        Bo   Report   Report
10       Bo   Report   Report

пена, промыть, повторить. Времена 52. И, как заметил @DS_UNI, хотя отдельные столбцы для недели и года были бы хорошими, они победили бы конечную цель - временные ряды, растянувшиеся на более чем один год ... но не позволяющие себе полностью уйти орехи, я был бы просто счастлив, если бы мог повторить 52 недели одного года.

Как я уже сказал, приведенный выше код работает. Я просто ищу способ сделать это, а не повторять его до тошноты.

Вот текст dput для усеченных данных (сохраните как test1.txt в вашем рабочем каталоге):

structure(list(`W1_2019_EIDSR-Timely_Report` = c(NA_real_, NA_real_,  NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_,  NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_,  NA_real_, NA_real_, NA_real_, NA_real_), W1_2019_EIDSR_Total_Malaria_cases = c(0,  NA, 51, NA, 64, 86, 92, 47, 46, 35, 33, NA, NA, 77, 35, 7, 24,  27, 14, 72), W1_2019_EIDSR_Date_Received = c(NA_character_, NA_character_,  NA_character_, NA_character_, NA_character_, NA_character_, NA_character_,  NA_character_, NA_character_, NA_character_, NA_character_, NA_character_,  NA_character_, NA_character_, NA_character_, NA_character_, NA_character_,  NA_character_, NA_character_, NA_character_), `W1_2019_EIDSR-Mobile_Internet` = c(NA_real_,  NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_,  NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_,  NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), `W1_2019_EIDSR-Mobile_SMS` = c(NA_real_,  NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_,  NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_,  NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), `W2_2019_EIDSR-Timely_Report`
= c(NA_real_,  NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_,  NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_,  NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), W2_2019_EIDSR_Total_Malaria_cases = c(55,  NA, 44, NA, 38, 26, 29, 40, 59, 18, 48, NA, NA, 37, 34, 51, 34,  38, 13, 56), W2_2019_EIDSR_Date_Received = c(NA_character_, NA_character_,  NA_character_, NA_character_, NA_character_, NA_character_, NA_character_,  NA_character_, NA_character_, NA_character_, NA_character_, NA_character_,  NA_character_, NA_character_, NA_character_, NA_character_, NA_character_,  NA_character_, NA_character_, NA_character_), `W2_2019_EIDSR-Mobile_Internet` = c(NA_real_,  NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_,  NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_,  NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), `W2_2019_EIDSR-Mobile_SMS` = c(NA_real_,  NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_,  NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_,  NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), district = c("Bo",  "Bo", "Bo", "Bo", "Bo", "Bo", "Bo", "Bo", "Bo", "Bo", "Bo", "Bo",  "Bo", "Bo", "Bo", "Bo", "Bo", "Bo", "Bo", "Bo")), .Names = c("W1_2019_EIDSR-Timely_Report",  "W1_2019_EIDSR_Total_Malaria_cases", "W1_2019_EIDSR_Date_Received",  "W1_2019_EIDSR-Mobile_Internet", "W1_2019_EIDSR-Mobile_SMS",  "W2_2019_EIDSR-Timely_Report", "W2_2019_EIDSR_Total_Malaria_cases",  "W2_2019_EIDSR_Date_Received", "W2_2019_EIDSR-Mobile_Internet",  "W2_2019_EIDSR-Mobile_SMS", "district"), row.names = c(NA, -20L ), class = c("tbl_df", "tbl", "data.frame"))

1 Ответ

1 голос
/ 17 апреля 2019

Ваши данные должны выглядеть примерно так (я бы также предпочел иметь столбец для недели и столбец для года). И, скорее всего, есть способ манипулировать, чтобы получить то, что вы хотите.

library(dplyr)
library(reshape2)

eidsr %>% 
  # values should be in a column (not in headers) 
  melt(id.var = 'district') %>% 
  # extract the new variables
  mutate(week_year = substr(variable, 1, 7),
         variable = sub(".*EIDSR[- _]", "", variable)) %>% 
  # assuming missing values don't have a specific meaning you can just remove them
  na.omit()

#     district            variable value week_year
# 21        Bo Total_Malaria_cases     0   W1_2019
# 23        Bo Total_Malaria_cases    51   W1_2019
# 25        Bo Total_Malaria_cases    64   W1_2019
# 26        Bo Total_Malaria_cases    86   W1_2019
# 27        Bo Total_Malaria_cases    92   W1_2019
# 28        Bo Total_Malaria_cases    47   W1_2019
# 29        Bo Total_Malaria_cases    46   W1_2019
# 30        Bo Total_Malaria_cases    35   W1_2019

Я вижу, что вы теряете терпение, поэтому, если вы ДОЛЖНЫ использовать цикл, вы должны использовать одну из функций применения, а для тех, кому нужна функция, многократно примененная к вектору или списку:

wacky_fun <- function(x_chr){
  malaria_col <- paste0(x_chr, '_EIDSR_Total_Malaria_cases')
  sms_col <- paste0(x_chr, '_EIDSR-Mobile_SMS')
  internet_col <- paste0(x_chr, '_EIDSR-Mobile_Internet')

  mode_col <- rep("NoRep", nrow(eidsr))
  mode_col[eidsr[malaria_col]>0] <- "Report"
  mode_col[eidsr[sms_col]==1] <- "Mobile_SMS"
  mode_col[eidsr[internet_col]==1] <- "Mobile_Internet"

  return(mode_col)
}

Мы применим эту функцию ко всем неделям в данных

# get the unique weeks in the headers 
weeks <- names(eidsr)[grepl('W[[:digit:]]_[[:digit:]]{4}', names(eidsr))] %>% 
  substr(1, 7) %>% 
  unique()
# apply the function on all the weeks, bind them with the district, and convert to data.frame
cbind('district' = eidsr$district, sapply(weeks, wacky_fun)) %>% 
  as.data.frame()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...