readr::read_csv()
имеет более 20 аргументов, многие из которых редко используются, например, locale
, skip
, na
. Перенос менее востребованных настроек в объект опций позволяет:library(S7)
.locale <- new_property(
class_list,
default = readr::default_locale(),
validator = function(value) {
dnames <- value$date_names
invalid <- !rlang::is_character(dnames$mon, n = 12) ||
!rlang::is_character(dnames$mon_ab, n = 12) ||
!rlang::is_character(dnames$day, n = 7) ||
!rlang::is_character(dnames$day_ab, n = 7) ||
!rlang::is_character(dnames$am_pm, n = 2) || !rlang::is_scalar_character(value$date_format) || !rlang::is_scalar_character(value$time_format) || !rlang::is_scalar_character(value$decimal_mark) || !rlang::is_scalar_character(value$grouping_mark) || !rlang::is_scalar_character(value$tz) || !rlang::is_scalar_character(value$encoding)
if (invalid) {
"expected `locale` object"
}
}
)
locale
имеют правильный тип.na
quote
comment
trim_ws
skip
n_max
guess_max
name_repair
num_threads
progress
show_col_types
skip_empty_rows
lazy
locale
, na
, trim_ws
и другие:class_readr_opts <- new_class(
"readr_opts",
properties = list(
locale = .locale,
na = .na,
quote = .quote,
comment = .comment,
trim_ws = .trim_ws,
skip = .skip,
n_max = .n_max,
guess_max = .guess_max,
name_repair = .name_repair,
num_threads = .num_threads,
progress = .progress,
show_col_types = .show_col_types,
skip_empty_rows = .skip_empty_rows,
lazy = .lazy
)
)
opts <- class_readr_opts()
opts
read_csv <- function(
file,
col_names = TRUE,
col_types = NULL,
col_select = NULL,
id = NULL,
options = class_readr_opts()
) {
# function logic
}
options
, упростив вызов и настройку функции.S7
позволяет уменьшить сложность функций, сделать их более читаемыми и строго типизированными. Такой подход особенно полезен при разработке библиотек и сложных API.webR
— WebAssembly-компиляции R. Эта технология позволяет запускать R-код прямо в JavaScript-средах, открывая новые возможности для создания мобильных приложений. В этом посте разбираем, как это работает и что это значит для разработчиков.webR
— это специальная версия R, адаптированная для работы в WebAssembly. Если раньше R использовался преимущественно для серверных приложений (например, через Shiny
), то теперь его можно внедрять прямо в браузеры и мобильные устройства.webR
:webR
мобильные приложения, использующие R, в основном реализовывались через Shiny
и shinyMobile
. Однако такие решения имели ряд ограничений:webR
решает эти проблемы, позволяя создавать настоящие нативные мобильные приложения, которые:webR
— это революционная технология, которая может значительно изменить подход к созданию приложений. Это важный шаг для популяризации R за пределами традиционных областей его применения.install.packages("S7")
Range <- new_class("Range",
properties = list(
start = class_double,
end = class_double
),
validator = function(self) {
if (length(self@start) != 1) {
"@start must be length 1"
} else if (length(self@end) != 1) {
"@end must be length 1"
} else if (self@end < self@start) {
"@end must be greater than or equal to @start"
}
}
)
# Создаем корректный объект
valid_range <- new_object(Range, start = 1, end = 10)
print(valid_range)
# Проверка с некорректными данными
tryCatch(
new_object(Range, start = 10, end = 5),
error = function(e) message("Ошибка: ", e$message)
)
new_generic()
). Это упрощает настройку поведения для различных классов.greeting <- new_generic("greeting", function(x) NULL)
method(greeting, Range) <- function(x) {
paste("Диапазон начинается с", x@start, "и заканчивается", x@end)
}
greeting(valid_range) # Диапазон начинается с 1 и заканчивается 10
Employee <- new_class("Employee", parent = Range, properties = list(
name = class_character
))
worker <- Employee(start = 9, end = 18, name = "Jane")
print(worker)
patchwork 1.3.0
, которая привнесла интересные возможности для работы с таблицами в графических композициях. Теперь можно легко интегрировать таблицы gt
с графиками, используя функции wrap_elements()
и wrap_table()
. Пример простого графика с таблицей:library(patchwork)
library(ggplot2)
library(gt)
p1 <- ggplot(airquality) +
geom_line(aes(x = Day, y = Temp, colour = month.name[Month])) +
labs(colour = "Month")
aq <- airquality[sample(nrow(airquality), 10), ]
p1 + wrap_table(aq, space = "free_y")
p1 <- ggplot(mtcars) +
geom_point(aes(mpg, disp)) +
ggtitle('Scatter plot')
p2 <- ggplot(mtcars) +
geom_bar(aes(factor(cyl))) +
ggtitle('Bar plot')
layout <- c(
area(t = 1, l = 1, b = 2, r = 2),
area(t = 1, l = 3, b = 2, r = 3)
)
p1 + p2 + plot_layout(design = layout)
patchwork
в посте "Как расположить несколько ggplot2 графиков на одном изображении".dplyr
для таких задач существует механизм tidy evaluation, и одними из ключевых инструментов являются функции sym()
, syms()
и оператор !!
.library(dplyr)
data <- tibble(
Area = c('IT', 'Finance', NA),
Date = as.Date(c('2023-01-01', NA, '2023-03-15'))
)
# Фильтруем строки, где нет пропусков в столбцах 'Area' и 'Date'
filtered_data <- data %>%
filter(!is.na(Area), !is.na(Date))
filter()
не сработает.sym()
преобразует строку в символ (символ — это объект, который может быть интерпретирован как имя переменной), а оператор !!
используется для развертывания этого символа в выражении. Давайте рассмотрим, как это работает:library(dplyr)
# Функция для фильтрации данных на основе имен столбцов, переданных как строки
filter_data <- function(data, col_name1, col_name2) {
col1 <- sym(col_name1)
col2 <- sym(col_name2)
data %>%
filter(!is.na(!!col1), !is.na(!!col2))
}
# Пример данных
data <- tibble(
Area = c('IT', 'Finance', NA),
Date = as.Date(c('2023-01-01', NA, '2023-03-15'))
)
# Фильтруем данные, используя имена столбцов как строки
filtered_data <- filter_data(data, 'Area', 'Date')
print(filtered_data)
sym(col_name1)
и sym(col_name2)
преобразуют строки в символы, которые затем могут использоваться в dplyr::filter()
.!!
разворачивает символ в выражении, позволяя использовать его как имя переменной в функции filter()
.library(dplyr)
# Функция для фильтрации нескольких столбцов
filter_multiple <- function(data, col_names) {
cols <- syms(col_names)
data %>%
filter(across(all_of(col_names), ~ !is.na(.)))
}
# Пример данных
data <- tibble(
Area = c('IT', 'Finance', NA),
Date = as.Date(c('2023-01-01', NA, '2023-03-15')),
Amount = c(1000, 2000, NA)
)
# Фильтруем строки, где нет пропусков в нескольких столбцах
filtered_data <- filter_multiple(data, c('Area', 'Date', 'Amount'))
print(filtered_data)
syms(col_names)
преобразует вектор строк в список символов.across()
вместе с all_of()
позволяет удобно применить фильтр ко всем указанным столбцам.sym()
, syms()
и оператора !!
— это мощный инструмент для написания гибкого и динамического кода в R. Он особенно полезен при работе с большими данными и пакетами вроде dplyr, когда имена столбцов не известны заранее или приходят из пользовательского ввода.split()
разбить основную таблицу, на подтаблицы, о том как это сделать я уже рассказывал. purrr:walk()
, и вывести по очереди их на печать. library(knitr)
library(kableExtra)
library(purrr)
# разбиваем большую таблицу на список подтаблиц
df_list <- split(df, df$type)
# печатаем по очереди каждую из подтаблиц
purrr::walk(names(df_list), ~{
cat(
knitr::kable(df_list[[.x]], caption = paste("Таблица для типа:", .x), format = "html") %>%
kableExtra::kable_styling(full_width = FALSE) %>%
as.character()
)
cat("\n\n") # Добавляем пустые строки между таблицами
})
df
на список подтаблиц;purrr::walk()
для итерации по именам подтаблиц в нашем списке;kable()
;kable_styling()
cat()
round()
в R округлила число 6.5 до 6, а Power BI - до 7.round()
использует не привычный нам математический способ округления, а так называемый банковский. Вот в чём их отличия:round()
попробуете округлить числа 2.5, 4.5, 6.5, то получите соответственно 2, 4, 6, а не ожидаемые 3, 5, 7.round_math <- function(x) {
sign(x) * floor(abs(x) + 0.5)
}
custom_round <- function(x, digits = 0) {
posneg <- sign(x) # Определяем знак числа
z <- abs(x) * 10^digits
z <- z + 0.5 # Добавляем 0.5 для округления вверх
z <- floor(z)
return(posneg * z / 10^digits)
}
install.packages(c("tuneR", "seewave", "googledrive", "googleAuthR", "googleLanguageR", "av"))
library(tuneR)
library(seewave)
library(googledrive)
library(googleAuthR)
library(googleLanguageR)
library(av)
speech_to_text_from_audio <- function(audio_file_path) {
# Определяем расширение файла
file_ext <- tolower(tools::file_ext(audio_file_path))
# Создаем временный WAV файл
temp_wav_file <- tempfile(fileext = ".wav")
# Обработка в зависимости от типа файла
if (file_ext == "mp3") {
audio <- readMP3(audio_file_path)
} else if (file_ext == "wav") {
audio <- readWave(audio_file_path)
} else if (file_ext == "ogg") {
# Конвертируем OGG в WAV
av_audio_convert(audio_file_path, temp_wav_file)
audio <- readWave(temp_wav_file)
} else {
stop("Неподдерживаемый формат файла. Поддерживаются только MP3, WAV и OGG.")
}
# Если аудио стерео, конвертируем в моно
if (audio@stereo) {
audio <- mono(audio, "both")
}
# Изменяем частоту дискретизации на 16000 Гц, только если текущая частота отличается
if (audio@samp.rate != 16000) {
audio_resampled <- resamp(audio, g = 16000, output = "Wave")
} else {
audio_resampled <- audio
}
# Записываем обработанное аудио во временный WAV файл
writeWave(audio_resampled, temp_wav_file)
# Выполняем распознавание речи
result <- tryCatch({
gl_speech(temp_wav_file,
languageCode = "ru-RU",
sampleRateHertz = 16000)$transcript
}, error = function(e) {
return(paste("Ошибка при распознавании речи:", e$message))
})
# Удаляем временный WAV файл
file.remove(temp_wav_file)
# Возвращаем результат
return(result$transcript)
}
# Пример использования:
# Не забудьте аутентифицироваться перед использованием функции
gl_auth("path/to/your/google_cloud_credentials.json")
# Теперь вы можете использовать функцию так:
mp3_file <- "path/to/your/voice.mp3"
ogg_file <- "path/to/your/voice.ogg"
transcript_mp3 <- speech_to_text_from_audio(mp3_file)
transcript_ogg <- speech_to_text_from_audio(ogg_file)
> transcript_mp3
[1] "небольшая текстовая начитка для преобразования речи в текст с помощью языка R"