Полезные советы и хитрости
Большинство из нас обычно предпочитают работать на одном языке, будь то R или python, но через какое-то время нам, возможно, придется переключиться на другой язык, вероятно, из-за таких причин, как требования к проекту, доступность определенного пакета и личные интересы. Поэтому я пишу эту серию для тех, кто уже хорошо разбирается в науке о данных на Python, но хочет изучить R. Я начну с основ и затрону следующие темы в этой статье.
- Структуры данных
- Подмножество
- Структуры управления
- Функции
- Векторизация
Структуры данных-
R имеет 6 атомарных классов, включая -символьный, числовой (действительный или десятичный), целочисленный и логический, имена которых не требуют пояснений. Давайте посмотрим на несколько структур данных в R.
Векторы
Вектор - это самая распространенная и основная структура данных в R
и в значительной степени рабочая лошадка R. Технически векторы могут быть одного из двух типов:
- Атомарные векторы - они похожи на одномерные
numpy
массивы в Python. Они могут содержать числовые, символьные или логические значения. В атомарных векторах все элементы вектора имеют один и тот же тип данных. - Списки- они похожи на
lists
в Python и, как и списки, могут содержать значения разных типов и даже другой список.
Вот пример того, как вы создаете атомарные векторы и списки.
# example of character, numerical, and logical vectors respectively. name <- c("Mike", "Lucy", "John") age <- c(20, 25, 30) student <- c(TRUE, FALSE, TRUE) # example of list student1 <- list("Mike", 20, TRUE)
Давайте посмотрим, как вы можете преобразовать из вектора в список и наоборот.
# convert vector to list name_list <- as.list(name) # convert list to vector student_vector <- unlist(student1)
Теперь вы можете задаться вопросом, что я только что сказал, что векторы не могут содержать более одного типа данных, но я все же смог преобразовать список в вектор. Фактически, когда вы конвертируете список в вектор, все элементы списка преобразуются в один тип данных. Например, когда мы конвертируем student1 в вектор, мы получаем вектор символов со всеми элементами в качестве символа.
student_vector <- unlist(student1) student_vector [1] "Mike" "20" "TRUE"
Производные объекты - Матрица, Массив и Фрейм данных являются производными объектами. Матрицы и фреймы данных являются прямоугольными объектами данных. Разница в том, что в матрице все должно быть одного типа данных, однако во фреймах данных могут быть разные типы данных в разных столбцах. Короче говоря, вы можете рассматривать матрицы как двумерные атомарные векторы, а фреймы данных как двумерные списки. Массивы похожи на матрицы, но могут иметь более двух измерений. Я расскажу об этих темах более подробно в следующей части.
Подмножество
Давайте быстро рассмотрим подмножество в R. Есть несколько отличий от python: -
- Индексирование начинается с 1 в R, в отличие от 0 в python
- И начальное, и конечное значения включаются во время нарезки, в отличие от python, где стоповое значение является исключительным.
- И начальное, и конечное значения должны быть указаны во время нарезки, в отличие от python, где, если вы не укажете начальное / конечное значение, оно будет относиться к первому / последнему значению соответственно.
Теперь мы знаем, что в python мы также можем использовать обратную индексацию для ссылки на элементы из последнего с помощью оператора -
. К сожалению, это невозможно в R. Однако есть способы, которыми мы можем достичь аналогичных результатов.
# example of reverse indexing in python x = list(range(1,11)) # access the last element x[-1] # access last 5 elements x[-5:]
Вы можете добиться аналогичного в R следующим образом.
x = 1:10
# access the last element
x[length(x)]
# access last 5 elements using following three ways
x[ (length(x) - 4): length(x)]
x[length(x) - (4:0)]
x[seq.int(to = length(x), length.out = 5)]
Кроме того, вы также можете использовать tail
для доступа к последнему элементу n
, как показано ниже. Этот метод не только более читабелен, но и безопаснее работать, если вы не уверены, что длина x всегда будет превышать n
.
# access last 5 elementstail(x,5) [1] 6 7 8 9 10
# access last 20 elementstail(x, 20) [1] 1 2 3 4 5 6 7 8 9 10
Структуры управления
Давайте рассмотрим некоторые из основных структур управления: -
if, else: - Ниже приведен код if, else в Python.
# code for if, else in python if condition 1: # do something elif condition 2: # do something else: # do something else
Кроме того, ниже приведен код if else в R.
# code for if, else in R if (condition 1) { # do something } else if (condition 2) { # do something } else # do something else
Хотя синтаксис довольно знаком, вы могли бы заметить, что в R-
- отступы предложений не обязательны, вместо этого вы должны использовать фигурные скобки
{}
для обозначения блока кода. Также обратите внимание, что если блок кода представляет собой одну строку, вы также можете пропустить фигурные скобки. - условия должны быть записаны в изогнутых
()
скобках. else if
используется вместоelif
.
Также обратите внимание, что операторы else if
и else
должны начинаться в той же строке, в которой заканчивается фигурная скобка if
.
Цикл For-. Синтаксис цикла for также очень похож на Python и R, просто помните о моментах, которые я упомянул в разделе if, else выше для. Ниже приведен пример цикла for в Python.
for i in range(1,11): print(i)
Ниже приведен соответствующий код в R.
for (i in 1:10) {
print(i)
}
Следует помнить о следующих моментах:
- R использует
next
keyword, который аналогиченcontinue
keyword в Python - оба языка используют ключевое слово
break
для выхода из цикла.
Функции
Теперь мы все знакомы с базовой структурой объявления функции в Python, как описано ниже.
def functionName( parameters/arguments ): #body of the function return [expression] # this is a sample function in python def addFunction(x, y): z = x + y return z
Точно так же мы можем определить функцию в R следующим образом:
functionName<- function(
parameters/arguments) {
#body of the functionreturn( expression ) }
# this is a sample function in R
addFunction <- function( x, y){ z <- x + y return (z) }
Обратите внимание, что в R нет необходимости писать return
функцию, чтобы возвращать значение из функции. function()
сам возвращает последнее оцененное значение даже без включения функции return()
. Например, как показано в примере ниже.
addFunction <- function( x, y){ z <- x + y z }
Векторизация
Все мы знакомы с пониманием списков в Python, где вы можете написать весь цикл for в одном предложении.
# basic syntax of list comprehension [ expression for item in list if conditional ] # an example of list comprehension # construct a range of values xs = range(1,11) # filter xs for even values xs = [x for x in xs if x % 2 == 0]
R также имеет такой же элегантный (или, возможно, лучший) способ делать вещи, аналогичные пониманию списка через векторизацию, где векторизованные функции могут применяться к любому вектору. Например, приведенный выше код может быть реализован в R следующим образом: -
# construct a range of values xs <- 1:10 # xs == c(1,2,3,4,5,6,7,8,9,10) # filter xs for even values x[ ifelse(x %%2 == 0, TRUE, FALSE) ] # basically vector[ ifelse( condition , yes, no)]
Давайте сделаем еще один шаг и рассмотрим пример функции paste()
в R, которая просто используется для соединения двух строк. Однако, когда вы передаете векторы в качестве аргументов функции paste()
, R применит эту функцию поэлементно к векторам и вернет результирующий вектор, как показано в примере ниже.
authors <- c("Andrie","Joris") lastnames <- c("de Vries","Meys") paste(authors,lastnames) [1] "Andrie de Vries" "Joris Meys"
Как вы можете видеть в приведенном выше примере, R взял первый элемент из двух векторов и затем применил функцию, затем аналогичным образом взял вторые элементы и повторил процесс. Однако давайте посмотрим, что происходит, когда два вектора имеют неравную длину в примере ниже.
firstnames <- c("Joris", "Carolien", "Koen") lastname <- c("Meys") paste(firstnames,lastname) [1] "Joris Meys" "Carolien Meys" "Koen Meys"
В случае, если векторы имеют неравную длину, R повторяет меньший вектор до тех пор, пока не будет исчерпан каждый элемент более длинного вектора. Векторизованная операция всегда приводит к вектору длины, равной длине более длинного вектора.
Надеюсь, вам понравилась первая часть этой серии, и это поможет вам быстрее перейти с python на R. Пожалуйста, не стесняйтесь комментировать и задавать вопросы или вносить какие-либо предложения. Вы также можете ознакомиться с некоторыми другими моими статьями здесь.