Полезные советы и хитрости

Большинство из нас обычно предпочитают работать на одном языке, будь то 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 elements
tail(x,5)
[1]  6  7  8  9 10
# access last 20 elements
tail(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 function
    return( 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. Пожалуйста, не стесняйтесь комментировать и задавать вопросы или вносить какие-либо предложения. Вы также можете ознакомиться с некоторыми другими моими статьями здесь.