Проверьте, присутствует ли переменная в каждом элементе списка и условного преобразования - PullRequest
0 голосов
/ 04 мая 2018

Я столкнулся с несколько сложной проблемой. У меня есть список, элементы которого являются датафреймами. В этих фреймах данных гарантированно будет только один из двух столбцов с конкретными именами, которые содержат переменную POSIXct. Мне нужно выполнить условное mutate для этих столбцов, чтобы отформатировать их от POSIXct до '%d.%m.%Y'. Пожалуйста, рассмотрите этот пример:

library(lubridate)
rm(list = ls())

data <- list(a = tibble(ServiceStart = now(), y = 1),
             b = tibble(y = 1, BillDate = now()))

format(now(), format='%d.%m.%Y')

Это может показаться довольно простым, но я бы хотел, чтобы это работало автоматически, например, Мне нужна условная команда, которая распознает, когда нужно изменить переменную ServiceStart, а когда - изменить переменную BillDate. Я до сих пор придумал это:

if("ServiceStart" %in% names(data[[1]]))
{
  data %>%
    map(~mutate(., ServiceStart = format(data[[1]]$ServiceStart, format='%d.%m.%Y')))
} else {
  data %>%
    map(~mutate(., BillDate = format(data[[1]]$BillDate, format='%d.%m.%Y')))
}

Это, очевидно, не работает, потому что data[[1]] говорит R указывать только первый кадр данных в списке, когда я хочу, чтобы он делал это для каждого элемента списка индивидуально.

Я считаю, что важно дать некоторый дополнительный контекст относительно того, почему я делаю это: Чтобы упростить / ускорить процесс очистки данных, я написал короткий скрипт, который импортирует все файлы Excel в заданную папку в качестве элементов списка. Затем я использую map(), чтобы удалить все не алфавитно-цифровые символы из столбца. Я заканчиваю этот процесс, используя lapply(), чтобы экспортировать каждый элемент списка (все кадры данных) как очищенные файлы Excel. Это работает как задумано:

library(tidyverse)
library(readxl)
library(writexl)
rm(list = ls())

dir.create(file.path("data", "cleaned")) #create "cleaned" folder if needed

filenames <- list.files("data", pattern="*.xlsx", full.names = TRUE) #extract file names

data_raw <- lapply(filenames, read_xlsx) #import all files as elements of list

data_edit <- data_raw %>%  #clean column from non-alphanumeric characters (main purpose!)
  map(~mutate(., InitiatorZSR = str_replace_all(InitiatorZSR, "[^[:alnum:]]", "")))

names(data_edit) <- substr(filenames, 6, 7) #name dataframes within list (usually a number)

files <- list.files("data", pattern="*.xlsx", full.names = F)
filenames <- paste("data/cleaned/", files, sep = "") #prepare export to "cleaned" folder

lapply(seq_along(data_edit), function(i){
  write_xlsx(data_edit[[i]], filenames[i])
}) #export all elements of list as excel files to folder "cleaned"

Проблема заключается в том, что столбцы даты в файлах импорта в формате '%d.%m.%Y', к сожалению, анализируются в POSIXct при импорте с помощью readxl, который я не могу отключить. Это делает файлы непригодными для меня. Поскольку этот сценарий был написан для автоматической работы с любым универсальным файлом импорта, я не могу настроить таргетинг и изменение этих столбцов вручную, так как это противоречит цели.

Меня вдохновил этот пост Открытие всех файлов в папке и применение функции , чтобы попробовать этот метод.

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

Ответы [ 2 ]

0 голосов
/ 04 мая 2018

Вы ищете rapply

rapply(data,format,"POSIXct",how = "replace",format="%d---%m----%Y")#You can use any fromating you want
$a
# A tibble: 1 x 2
  ServiceStart        y
  <chr>           <dbl>
1 04---05----2018    1.

$b
# A tibble: 1 x 2
      y BillDate       
  <dbl> <chr>          
1    1. 04---05----2018
0 голосов
/ 04 мая 2018

Надеюсь, я правильно понял ваш вопрос, и это поможет вам.

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

library(lubridate)

data <- list(a = tibble(ServiceStart = now(), y = 1),
         b = tibble(y = 1, BillDate = now()))

format_col <- function(x) {
    if("ServiceStart" %in% names(x))
    {
        x$ServiceStart <- format(x$ServiceStart, format='%d.%m.%Y')
        x
    } else {
        x$BillDate <- format(x$BillDate, format='%d.%m.%Y')
        x
    }
}

data <- lapply(data, format_col)

data

# $a
# # A tibble: 1 x 2
#   ServiceStart     y
#   <chr>        <dbl>
# 1 04.05.2018    1.00

# $b
# # A tibble: 1 x 2
#   y BillDate  
#   <dbl> <chr>     
# 1  1.00 04.05.2018
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...