Около data.table

Π’Π°Π·ΠΈ Π±Π΅Π»Π΅ΠΆΠΊΠ° Ρ‰Π΅ прСдставлява интСрСс Π·Π° ΠΎΠ½Π΅Π·ΠΈ, ΠΊΠΎΠΈΡ‚ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ°Ρ‚Π° Π·Π° ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° Π½Π° Ρ‚Π°Π±Π»ΠΈΡ‡Π½ΠΈ Π΄Π°Π½Π½ΠΈ Π·Π° R - data.table, ΠΈ ΠΌΠΎΠΆΠ΅ Π΄Π° сС Ρ€Π°Π΄Π²Π°Ρ‚ Π΄Π° видят Π³ΡŠΠ²ΠΊΠ°Π²ΠΎΡΡ‚Ρ‚Π° Π½Π° Π½Π΅ΠΉΠ½ΠΎΡ‚ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ Π² Ρ€Π°Π·Π»ΠΈΡ‡Π½ΠΈ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ΠΈ.

Π’Π΄ΡŠΡ…Π½ΠΎΠ²Π΅Π½ ΠΎΡ‚ Π΄ΠΎΠ±ΡŠΡ€ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ КолСги, ΠΈ надявайки сС, Ρ‡Π΅ Π²Π΅Ρ‡Π΅ стС ΠΏΡ€ΠΎΡ‡Π΅Π»ΠΈ Π½Π΅Π³ΠΎΠ²Π°Ρ‚Π° статия, ΠΏΡ€Π΅Π΄Π»Π°Π³Π°ΠΌ Π΄Π° сС Π·Π°Π΄ΡŠΠ»Π±ΠΎΡ‡ΠΈΠΌ Π² оптимизацията Π½Π° ΠΊΠΎΠ΄Π° ΠΈ въз основа Π½Π° производитСлността Ρ‚Π°Π±Π»ΠΈΡ†Π° с Π΄Π°Π½Π½ΠΈ.

Π’ΡŠΠ²Π΅Π΄Π΅Π½ΠΈΠ΅: ΠžΡ‚ΠΊΡŠΠ΄Π΅ ΠΈΠ΄Π²Π° data.table?

Най-Π΄ΠΎΠ±Ρ€Π΅ Π΅ Π΄Π° Π·Π°ΠΏΠΎΡ‡Π½Π΅Ρ‚Π΅ Π΄Π° сС Π·Π°ΠΏΠΎΠ·Π½Π°Π²Π°Ρ‚Π΅ с Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ°Ρ‚Π° ΠΌΠ°Π»ΠΊΠΎ ΠΎΡ‚Π΄Π°Π»Π΅Ρ‡, Π° ΠΈΠΌΠ΅Π½Π½ΠΎ със структуритС ΠΎΡ‚ Π΄Π°Π½Π½ΠΈ, ΠΎΡ‚ ΠΊΠΎΠΈΡ‚ΠΎ ΠΌΠΎΠΆΠ΅ Π΄Π° бъдС ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ ΠΎΠ±Π΅ΠΊΡ‚ΡŠΡ‚ data.table (Π½Π°Ρ€ΠΈΡ‡Π°Π½ ΠΏΠΎ-Π½Π°Ρ‚Π°Ρ‚ΡŠΠΊ DT).

Массив

Код

## arrays ---------

arrmatr <- array(1:20, c(4,5))

class(arrmatr)

typeof(arrmatr)

is.array(arrmatr)

is.matrix(arrmatr)

Π•Π΄Π½Π° Ρ‚Π°ΠΊΠ°Π²Π° структура Π΅ масив (?Π±Π°Π·Π°::масив). ΠšΠ°ΠΊΡ‚ΠΎ ΠΈ Π² Π΄Ρ€ΡƒΠ³ΠΈ Π΅Π·ΠΈΡ†ΠΈ, Ρ‚ΡƒΠΊ масивитС са ΠΌΠ½ΠΎΠ³ΠΎΠΈΠ·ΠΌΠ΅Ρ€Π½ΠΈ. Π˜Π½Ρ‚Π΅Ρ€Π΅ΡΠ½ΠΎΡ‚ΠΎ ΠΎΠ±Π°Ρ‡Π΅ Π΅, Ρ‡Π΅ Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π΄Π²ΡƒΠΌΠ΅Ρ€Π΅Π½ масив Π·Π°ΠΏΠΎΡ‡Π²Π° Π΄Π° наслСдява свойства ΠΎΡ‚ матричния клас (?base::matrix), ΠΈ Π΅Π΄Π½ΠΎΠΌΠ΅Ρ€Π΅Π½ масив, ΠΊΠΎΠΉΡ‚ΠΎ ΡΡŠΡ‰ΠΎ Π΅ Π²Π°ΠΆΠ΅Π½, Π½Π΅ наслСдява ΠΎΡ‚ Π²Π΅ΠΊΡ‚ΠΎΡ€ (?Π±Π°Π·Π°::Π²Π΅ΠΊΡ‚ΠΎΡ€).

Врябва Π΄Π° сС Ρ€Π°Π·Π±Π΅Ρ€Π΅, Ρ‡Π΅ Ρ‚ΠΈΠΏΡŠΡ‚ Π΄Π°Π½Π½ΠΈ, ΡΡŠΠ΄ΡŠΡ€ΠΆΠ°Ρ‰ΠΈ сС във всСки ΠΎΠ±Π΅ΠΊΡ‚, трябва Π΄Π° сС провСрява с функцията Π±Π°Π·Π°::Ρ‚ΠΈΠΏ, ΠΊΠΎΠ΅Ρ‚ΠΎ Π²Ρ€ΡŠΡ‰Π° Π²ΡŠΡ‚Ρ€Π΅ΡˆΠ½ΠΎΡ‚ΠΎ описаниС Π½Π° Ρ‚ΠΈΠΏΠ° спорСд R Π²ΡŠΡ‚Ρ€Π΅ΡˆΠ½ΠΈ части - общият ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ» Π½Π° Π΅Π·ΠΈΠΊΠ°, ΡΠ²ΡŠΡ€Π·Π°Π½ с ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π»Π° C.

Π”Ρ€ΡƒΠ³Π° ΠΊΠΎΠΌΠ°Π½Π΄Π° Π·Π° опрСдСлянС Π½Π° класа Π½Π° ΠΎΠ±Π΅ΠΊΡ‚ Π΅ Π±Π°Π·Π° :: клас, Π² случай Π½Π° Π²Π΅ΠΊΡ‚ΠΎΡ€ΠΈ, Π²Ρ€ΡŠΡ‰Π° вСкторния Ρ‚ΠΈΠΏ (Ρ€Π°Π·Π»ΠΈΡ‡Π°Π²Π° сС ΠΏΠΎ ΠΈΠΌΠ΅ ΠΎΡ‚ Π²ΡŠΡ‚Ρ€Π΅ΡˆΠ½ΠΈΡ, Π½ΠΎ ΡΡŠΡ‰ΠΎ Ρ‚Π°ΠΊΠ° Π²ΠΈ позволява Π΄Π° Ρ€Π°Π·Π±Π΅Ρ€Π΅Ρ‚Π΅ Ρ‚ΠΈΠΏΠ° Π΄Π°Π½Π½ΠΈ).

Бписък

ΠžΡ‚ Π΄Π²ΡƒΠΈΠ·ΠΌΠ΅Ρ€Π΅Π½ масив, извСстСн ΡΡŠΡ‰ΠΎ ΠΊΠ°Ρ‚ΠΎ ΠΌΠ°Ρ‚Ρ€ΠΈΡ†Π°, ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΠΎΡ‚ΠΈΠ΄Π΅Ρ‚Π΅ Π΄ΠΎ списъка (?base::list).

Код

## lists ------------------

mylist <- as.list(arrmatr)

is.vector(mylist)

is.list(mylist)

Няколко Π½Π΅Ρ‰Π° сС случват Π΅Π΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ:

  • Π’Ρ‚ΠΎΡ€ΠΎΡ‚ΠΎ ΠΈΠ·ΠΌΠ΅Ρ€Π΅Π½ΠΈΠ΅ Π½Π° ΠΌΠ°Ρ‚Ρ€ΠΈΡ†Π°Ρ‚Π° сС свива, тоСст ΠΏΠΎΠ»ΡƒΡ‡Π°Π²Π°ΠΌΠ΅ ΠΈ списък, ΠΈ Π²Π΅ΠΊΡ‚ΠΎΡ€ Π΅Π΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ.
  • По Ρ‚ΠΎΠ·ΠΈ Π½Π°Ρ‡ΠΈΠ½ ΡΠΏΠΈΡΡŠΠΊΡŠΡ‚ наслСдява ΠΎΡ‚ Ρ‚Π΅Π·ΠΈ класовС. Врябва Π΄Π° сС ΠΈΠΌΠ° ΠΏΡ€Π΅Π΄Π²ΠΈΠ΄, Ρ‡Π΅ Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚ ΠΎΡ‚ списък Ρ‰Π΅ ΡΡŠΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²Π° Π½Π° Π΅Π΄Π½Π° (скаларна) стойност ΠΎΡ‚ ΠΊΠ»Π΅Ρ‚ΠΊΠ° ΠΎΡ‚ ΠΌΠ°Ρ‚Ρ€ΠΈΡ†Π°Ρ‚Π° Π½Π° масива.

Въй ΠΊΠ°Ρ‚ΠΎ ΡΠΏΠΈΡΡŠΠΊΡŠΡ‚ ΡΡŠΡ‰ΠΎ Π΅ Π²Π΅ΠΊΡ‚ΠΎΡ€, някои Π²Π΅ΠΊΡ‚ΠΎΡ€Π½ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° Π±ΡŠΠ΄Π°Ρ‚ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈ към Π½Π΅Π³ΠΎ.

Dataframe

ΠœΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΠΏΡ€Π΅ΠΌΠΈΠ½Π΅Ρ‚Π΅ ΠΎΡ‚ списък, ΠΌΠ°Ρ‚Ρ€ΠΈΡ†Π° ΠΈΠ»ΠΈ Π²Π΅ΠΊΡ‚ΠΎΡ€ към Ρ€Π°ΠΌΠΊΠ° с Π΄Π°Π½Π½ΠΈ (?base::data.frame).

Код

## data.frames ------------

df <- as.data.frame(arrmatr)
df2 <- as.data.frame(mylist)

is.list(df)

df$V6 <- df$V1 + df$V2

Какво Π΅ интСрСсно Π·Π° Π½Π΅Π³ΠΎ: Ρ€Π°ΠΌΠΊΠ°Ρ‚Π° с Π΄Π°Π½Π½ΠΈ наслСдява ΠΎΡ‚ списъка! ΠšΠΎΠ»ΠΎΠ½ΠΈΡ‚Π΅ Π½Π° Dataframe са ΠΊΠ»Π΅Ρ‚ΠΊΠΈ ΠΎΡ‚ списък. Π’ΠΎΠ²Π° Ρ‰Π΅ бъдС Π²Π°ΠΆΠ½ΠΎ ΠΏΠΎ-късно, ΠΊΠΎΠ³Π°Ρ‚ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈ към ΡΠΏΠΈΡΡŠΡ†ΠΈ.

Ρ‚Π°Π±Π»ΠΈΡ†Π° с Π΄Π°Π½Π½ΠΈ

Π’Π·Π΅ΠΌΠ΅Ρ‚Π΅ DT (?data.table::data.table) ΠΌΠΎΠΆΠ΅ Π΄Π° бъдС ΠΎΡ‚ Ρ€Π°ΠΌΠΊΠ° с Π΄Π°Π½Π½ΠΈ, списък, Π²Π΅ΠΊΡ‚ΠΎΡ€ ΠΈΠ»ΠΈ ΠΌΠ°Ρ‚Ρ€ΠΈΡ†Π°. НапримСр, Ρ‚Π°ΠΊΠ° (Π½Π° място).

Код

## data.tables -----------------------
library(data.table)

data.table::setDT(df)

is.list(df)

is.data.frame(df)

is.data.table(df)

ПолСзно Π΅, ΠΏΠΎΠ΄ΠΎΠ±Π½ΠΎ Π½Π° Ρ€Π°ΠΌΠΊΠ° с Π΄Π°Π½Π½ΠΈ, DT Π΄Π° наслСдява свойствата Π½Π° списък.

DT ΠΈ ΠΏΠ°ΠΌΠ΅Ρ‚

Π—Π° Ρ€Π°Π·Π»ΠΈΠΊΠ° ΠΎΡ‚ всички Π΄Ρ€ΡƒΠ³ΠΈ ΠΎΠ±Π΅ΠΊΡ‚ΠΈ Π² R base, DT сС ΠΏΡ€Π΅Π΄Π°Π²Π°Ρ‚ ΠΏΠΎ рСфСрСнция. Ако трябва Π΄Π° Π½Π°ΠΏΡ€Π°Π²ΠΈΡ‚Π΅ ΠΊΠΎΠΏΠΈΠ΅ Π² Π½ΠΎΠ²Π° област Π½Π° ΠΏΠ°ΠΌΠ΅Ρ‚Ρ‚Π°, ΠΈΠΌΠ°Ρ‚Π΅ Π½ΡƒΠΆΠ΄Π° ΠΎΡ‚ функция data.table::copy ΠΈΠ»ΠΈ трябва Π΄Π° Π½Π°ΠΏΡ€Π°Π²ΠΈΡ‚Π΅ сСлСкция ΠΎΡ‚ стария ΠΎΠ±Π΅ΠΊΡ‚.

Код

df2 <- df

df[V1 == 1, V2 := 999]

data.table::fsetdiff(df, df2)

df2 <- data.table::copy(df)

df[V1 == 2, V2 := 999]

data.table::fsetdiff(df, df2)

Π’ΠΎΠ²Π° Π·Π°Π²ΡŠΡ€ΡˆΠ²Π° Π²ΡŠΠ²Π΅Π΄Π΅Π½ΠΈΠ΅Ρ‚ΠΎ. DT Π΅ ΠΏΡ€ΠΎΠ΄ΡŠΠ»ΠΆΠ΅Π½ΠΈΠ΅ Π½Π° Ρ€Π°Π·Π²ΠΈΡ‚ΠΈΠ΅Ρ‚ΠΎ Π½Π° структуритС ΠΎΡ‚ Π΄Π°Π½Π½ΠΈ Π² R, ΠΊΠΎΠ΅Ρ‚ΠΎ сС дълТи Π³Π»Π°Π²Π½ΠΎ Π½Π° Ρ€Π°Π·ΡˆΠΈΡ€ΡΠ²Π°Π½Π΅Ρ‚ΠΎ ΠΈ ускоряванСто Π½Π° ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈΡ‚Π΅, ΠΈΠ·Π²ΡŠΡ€ΡˆΠ²Π°Π½ΠΈ Π²ΡŠΡ€Ρ…Ρƒ ΠΎΠ±Π΅ΠΊΡ‚ΠΈ ΠΎΡ‚ класа dataframe. Π’ ΡΡŠΡ‰ΠΎΡ‚ΠΎ Π²Ρ€Π΅ΠΌΠ΅ сС Π·Π°ΠΏΠ°Π·Π²Π° наслСдството ΠΎΡ‚ Π΄Ρ€ΡƒΠ³ΠΈ ΠΏΡ€ΠΈΠΌΠΈΡ‚ΠΈΠ²ΠΈ.

Някои ΠΏΡ€ΠΈΠΌΠ΅Ρ€ΠΈ Π·Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ Π½Π° свойства Π½Π° data.table

ΠšΠ°Ρ‚ΠΎ списък...

Π˜Ρ‚Π΅Ρ€ΠΈΡ€Π°Π½Π΅Ρ‚ΠΎ Π½Π° Ρ€Π΅Π΄ΠΎΠ²Π΅Ρ‚Π΅ Π½Π° Ρ€Π°ΠΌΠΊΠ° с Π΄Π°Π½Π½ΠΈ ΠΈΠ»ΠΈ DT Π½Π΅ Π΅ Π΄ΠΎΠ±Ρ€Π° идСя, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ ΠΊΠΎΠ΄ΡŠΡ‚ Π½Π° Ρ†ΠΈΠΊΡŠΠ»Π° Π² Π΅Π·ΠΈΠΊΠ° R ΠΌΠ½ΠΎΠ³ΠΎ ΠΏΠΎ-Π±Π°Π²Π½ΠΎ C, Π½ΠΎ Π΅ напълно възмоТно Π΄Π° ΠΏΡ€Π΅ΠΌΠΈΠ½Π΅Ρ‚Π΅ ΠΏΡ€Π΅Π· ΠΊΠΎΠ»ΠΎΠ½ΠΈΡ‚Π΅, ΠΊΠΎΠΈΡ‚ΠΎ ΠΎΠ±ΠΈΠΊΠ½ΠΎΠ²Π΅Π½ΠΎ са ΠΌΠ½ΠΎΠ³ΠΎ ΠΏΠΎ-ΠΌΠ°Π»ΠΊΠΈ. ΠŸΡ€Π΅ΠΌΠΈΠ½Π°Π²Π°ΠΉΠΊΠΈ ΠΏΡ€Π΅Π· ΠΊΠΎΠ»ΠΎΠ½ΠΈΡ‚Π΅, Π½Π΅ забравяйтС, Ρ‡Π΅ всяка ΠΊΠΎΠ»ΠΎΠ½Π° Π΅ Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚ ΠΎΡ‚ списък, ΠΎΠ±ΠΈΠΊΠ½ΠΎΠ²Π΅Π½ΠΎ ΡΡŠΠ΄ΡŠΡ€ΠΆΠ°Ρ‰ Π²Π΅ΠΊΡ‚ΠΎΡ€. И ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈΡ‚Π΅ Π²ΡŠΡ€Ρ…Ρƒ Π²Π΅ΠΊΡ‚ΠΎΡ€ΠΈ са Π΄ΠΎΠ±Ρ€Π΅ Π²Π΅ΠΊΡ‚ΠΎΡ€ΠΈΠ·ΠΈΡ€Π°Π½ΠΈ Π² основнитС Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π½Π° Π΅Π·ΠΈΠΊΠ°. ΠœΠΎΠΆΠ΅Ρ‚Π΅ ΡΡŠΡ‰ΠΎ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚Π΅ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ΠΈ Π·Π° ΠΈΠ·Π±ΠΎΡ€, ΠΎΠ±Ρ‰ΠΈ Π·Π° ΡΠΏΠΈΡΡŠΡ†ΠΈ ΠΈ Π²Π΅ΠΊΡ‚ΠΎΡ€ΠΈ: `[[`, `$`.

Код

## operations on data.tables ------------

#using list properties

df$'V1'[1]

df[['V1']]

df[[1]][1]

sapply(df, class)

sapply(df, function(x) sum(is.na(x)))

ВСкторизация

Ако ΠΈΠΌΠ° Π½ΡƒΠΆΠ΄Π° Π΄Π° ΠΏΡ€Π΅ΠΌΠΈΠ½Π΅Ρ‚Π΅ ΠΏΡ€Π΅Π· Π»ΠΈΠ½ΠΈΠΈΡ‚Π΅ Π½Π° голям DT, Π½Π°ΠΉ-Π΄ΠΎΠ±Ρ€ΠΎΡ‚ΠΎ Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ Π±ΠΈ Π±ΠΈΠ»ΠΎ Π΄Π° Π½Π°ΠΏΠΈΡˆΠ΅Ρ‚Π΅ функция с вСкторизация. Но Π°ΠΊΠΎ Ρ‚ΠΎΠ²Π° Π½Π΅ Ρ€Π°Π±ΠΎΡ‚ΠΈ, Ρ‚ΠΎΠ³Π°Π²Π° трябва Π΄Π° Π·Π°ΠΏΠΎΠΌΠ½ΠΈΡ‚Π΅, Ρ‡Π΅ Ρ†ΠΈΠΊΡŠΠ»ΡŠΡ‚ Π² DT всС ΠΎΡ‰Π΅ Π΅ ΠΏΠΎ-Π±ΡŠΡ€Π·ΠΎ ΠΎΡ‚ Ρ†ΠΈΠΊΡŠΠ»Π° R, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ сС ΠΈΠ·Π²ΡŠΡ€ΡˆΠ²Π° Π½Π° C.

НСка ΠΎΠΏΠΈΡ‚Π°ΠΌΠ΅ Π½Π° ΠΏΠΎ-голям ΠΏΡ€ΠΈΠΌΠ΅Ρ€ със 100K Ρ€Π΅Π΄Π°. Π©Π΅ ΠΈΠ·Π²Π»Π΅Ρ‡Π΅ΠΌ ΠΏΡŠΡ€Π²Π°Ρ‚Π° Π±ΡƒΠΊΠ²Π° ΠΎΡ‚ Π΄ΡƒΠΌΠΈΡ‚Π΅, Π²ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈ във Π²Π΅ΠΊΡ‚ΠΎΡ€Π½Π°Ρ‚Π° ΠΊΠΎΠ»ΠΎΠ½Π° w.

ОбновСно

Код

library(magrittr)
library(microbenchmark)

## Bigger example ----

rown <- 100000

dt <- 
	data.table(
		w = sapply(seq_len(rown), function(x) paste(sample(letters, 3, replace = T), collapse = ' '))
		, a = sample(letters, rown, replace = T)
		, b = runif(rown, -3, 3)
		, c = runif(rown, -3, 3)
		, e = rnorm(rown)
	) %>%
	.[, d := 1 + b + c + rnorm(nrow(.))]

# vectorization

microbenchmark({
	dt[
		, first_l := unlist(strsplit(w, split = ' ', fixed = T))[1]
		, by = 1:nrow(dt)
	   ]
})

# second

first_l_f <- function(sd)
{
	strsplit(sd, split = ' ', fixed = T) %>%
		do.call(rbind, .) %>%
		`[`(,1)
}

dt[, first_l := NULL]

microbenchmark({
	dt[
		, first_l := .(first_l_f(w))
		]
})

# third

first_l_f2 <- function(sd)
{
	strsplit(sd, split = ' ', fixed = T) %>%
		unlist %>%
		matrix(nrow = 3) %>%
		`[`(1,)
}

dt[, first_l := NULL]

microbenchmark({
	dt[
		, first_l := .(first_l_f2(w))
		]
})

ΠŸΡŠΡ€Π²ΠΎ изпълнСниС, ΠΈΡ‚Π΅Ρ€ΠΈΡ€Π°Π½Π΅ Π½Π° Ρ€Π΅Π΄ΠΎΠ²Π΅:

Π•Π΄ΠΈΠ½ΠΈΡ†Π°: милисСкунди
ΠΈΠ·Ρ€Π°Π· ΠΌΠΈΠ½
{dt[, `:=`(first_l, unlist(strsplit(w, split = " ", fixed = T))[1]), by = 1:nrow(dt)] } 439.6217
lq срСдна ΠΌΠ΅Π΄ΠΈΠ°Π½Π° uq max neval
451.9998 460.1593 456.2505 460.9147 621.4042 100

Π’Ρ‚ΠΎΡ€ΠΎΡ‚ΠΎ изпълнСниС, ΠΏΡ€ΠΈ ΠΊΠΎΠ΅Ρ‚ΠΎ вСкторизацията сС ΠΈΠ·Π²ΡŠΡ€ΡˆΠ²Π° Ρ‡Ρ€Π΅Π· ΠΏΡ€Π΅Π²Ρ€ΡŠΡ‰Π°Π½Π΅ Π½Π° списъка Π² ΠΌΠ°Ρ‚Ρ€ΠΈΡ†Π° ΠΈ Π²Π·Π΅ΠΌΠ°Π½Π΅ Π½Π° Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚ΠΈ ΠΎΡ‚ срСза с индСкс 1 (послСдното Π΅ самата вСкторизация). ΠšΠΎΡ€Π΅ΠΊΡ†ΠΈΡ: вСкторизация Π½Π° Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»Π½ΠΎ Π½ΠΈΠ²ΠΎ strsplit, ΠΊΠΎΠΉΡ‚ΠΎ ΠΌΠΎΠΆΠ΅ Π΄Π° ΠΏΡ€ΠΈΠ΅ΠΌΠ΅ Π²Π΅ΠΊΡ‚ΠΎΡ€ ΠΊΠ°Ρ‚ΠΎ Π²Ρ…ΠΎΠ΄. Оказва сС, Ρ‡Π΅ ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Π°Ρ‚Π° Π·Π° ΠΏΡ€Π΅Π²Ρ€ΡŠΡ‰Π°Π½Π΅ Π½Π° списък Π² ΠΌΠ°Ρ‚Ρ€ΠΈΡ†Π° Π΅ ΠΌΠ½ΠΎΠ³ΠΎ ΠΏΠΎ-Ρ‚Ρ€ΡƒΠ΄Π½Π° ΠΎΡ‚ самата вСкторизация, Π½ΠΎ Π² Ρ‚ΠΎΠ·ΠΈ случай Π΅ ΠΌΠ½ΠΎΠ³ΠΎ ΠΏΠΎ-Π±ΡŠΡ€Π·Π° ΠΎΡ‚ Π½Π΅Π²Π΅ΠΊΡ‚ΠΎΡ€ΠΈΠ·ΠΈΡ€Π°Π½Π°Ρ‚Π° вСрсия.

Π•Π΄ΠΈΠ½ΠΈΡ†Π°: милисСкунди
expr min lq срСдна ΠΌΠ΅Π΄ΠΈΠ°Π½Π° uq max neval
{ dt[, `:=`(first_l, .(first_l_f(w)))] } 93.07916 112.1381 161.9267 149.6863 185.9893 442.5199 100

УскорСниС ΠΏΠΎ ΠΌΠ΅Π΄ΠΈΠ°Π½Π° Π² 3 ΠΏΡŠΡ‚ΠΈ.

ВрСтият Ρ†ΠΈΠΊΡŠΠ», ΠΊΡŠΠ΄Π΅Ρ‚ΠΎ схСмата Π·Π° трансформация Π² ΠΌΠ°Ρ‚Ρ€ΠΈΡ†Π°Ρ‚Π° Π΅ ΠΏΡ€ΠΎΠΌΠ΅Π½Π΅Π½Π°.

Π•Π΄ΠΈΠ½ΠΈΡ†Π°: милисСкунди
expr min lq срСдна ΠΌΠ΅Π΄ΠΈΠ°Π½Π° uq max neval
{ dt[, `:=`(first_l, .(first_l_f2(w)))] } 32.60481 34.13679 40.4544 35.57115 42.11975 222.972 100

УскорСниС ΠΏΠΎ ΠΌΠ΅Π΄ΠΈΠ°Π½Π° Π² 13 ΠΏΡŠΡ‚ΠΈ.

Врябва Π΄Π° СкспСримСнтиратС с Ρ‚ΠΎΠ·ΠΈ Π²ΡŠΠΏΡ€ΠΎΡ, ΠΊΠΎΠ»ΠΊΠΎΡ‚ΠΎ ΠΏΠΎΠ²Π΅Ρ‡Π΅, Ρ‚ΠΎΠ»ΠΊΠΎΠ²Π° ΠΏΠΎ-Π΄ΠΎΠ±Ρ€Π΅ Ρ‰Π΅ бъдС.

Π”Ρ€ΡƒΠ³ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ с вСкторизация, ΠΊΡŠΠ΄Π΅Ρ‚ΠΎ ΡΡŠΡ‰ΠΎ ΠΈΠΌΠ° тСкст, Π½ΠΎ Π΅ близък Π΄ΠΎ Ρ€Π΅Π°Π»Π½ΠΈΡ‚Π΅ условия: Ρ€Π°Π·Π»ΠΈΡ‡Π½ΠΈ дълТини Π½Π° Π΄ΡƒΠΌΠΈΡ‚Π΅, Ρ€Π°Π·Π»ΠΈΡ‡Π΅Π½ Π±Ρ€ΠΎΠΉ Π΄ΡƒΠΌΠΈ. Врябва Π΄Π° ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚Π΅ ΠΏΡŠΡ€Π²ΠΈΡ‚Π΅ 3 Π΄ΡƒΠΌΠΈ. ΠΊΠ°Ρ‚ΠΎ Ρ‚ΠΎΠ²Π°:

Около data.table

Π’ΡƒΠΊ ΠΏΡ€Π΅Π΄ΠΈΡˆΠ½Π°Ρ‚Π° функция Π½Π΅ Ρ€Π°Π±ΠΎΡ‚ΠΈ, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ Π²Π΅ΠΊΡ‚ΠΎΡ€ΠΈΡ‚Π΅ са с Ρ€Π°Π·Π»ΠΈΡ‡Π½Π° дълТина ΠΈ Π½ΠΈΠ΅ Π·Π°Π΄Π°Π²Π°ΠΌΠ΅ Ρ€Π°Π·ΠΌΠ΅Ρ€Π° Π½Π° ΠΌΠ°Ρ‚Ρ€ΠΈΡ†Π°Ρ‚Π°. НСка ΠΏΠΎΠ²Ρ‚ΠΎΡ€ΠΈΠΌ Ρ‚ΠΎΠ²Π°, ΠΊΠ°Ρ‚ΠΎ сС Ρ€Π°Π·Ρ€ΠΎΠ²ΠΈΠΌ Π² ΠΈΠ½Ρ‚Π΅Ρ€Π½Π΅Ρ‚.

Код

# fourth

rown <- 100000

words <-
	sapply(
		seq_len(rown)
		, function(x){
			nwords <- rbinom(1, 10, 0.5)
			paste(
				sapply(
					seq_len(nwords)
					, function(x){
						paste(sample(letters, rbinom(1, 10, 0.5), replace = T), collapse = '')
					}
				)
				, collapse = ' '
			)
		}
	)

dt <- 
	data.table(
		w = words
		, a = sample(letters, rown, replace = T)
		, b = runif(rown, -3, 3)
		, c = runif(rown, -3, 3)
		, e = rnorm(rown)
	) %>%
	.[, d := 1 + b + c + rnorm(nrow(.))]

first_l_f3 <- function(sd, n)
{
	l <- strsplit(sd, split = ' ', fixed = T)
	
	maxl <- max(lengths(l))
	
	sapply(l, "length<-", maxl) %>%
		`[`(n,) %>%
		as.character
}

microbenchmark({
	dt[
		, (paste0('w_', 1:3)) := lapply(1:3, function(x) first_l_f3(w, x))
		]
})

dt[
	, (paste0('w_', 1:3)) := lapply(1:3, function(x) first_l_f3(w, x))
	]

Π•Π΄ΠΈΠ½ΠΈΡ†Π°: милисСкунди
expr min lq срСдна ΠΌΠ΅Π΄ΠΈΠ°Π½Π°

{dt[, `:=`((paste0(β€œw_”, 1:3)), strsplit(w, split = " ", фиксиран = T))] } 851.7623 916.071 1054.5 1035.199
uq max neval
1178.738 1356.816 100

Π‘ΠΊΡ€ΠΈΠΏΡ‚ΡŠΡ‚ сС изпълнявашС със срСдна скорост ΠΎΡ‚ 1 сСкунда. Π½Π΅ Π΅ лошо

Π‘Π²ΡŠΡ€Π·Π°Π½ΠΈ с Π΅Π΄Π½Π° Π²Π΅Ρ€ΠΈΠ³Π°...

ΠœΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° Ρ€Π°Π±ΠΎΡ‚ΠΈΡ‚Π΅ с DT ΠΎΠ±Π΅ΠΊΡ‚ΠΈ, ΠΊΠ°Ρ‚ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚Π΅ Π²Π΅Ρ€ΠΈΠΆΠ½ΠΎ ΡΠ²ΡŠΡ€Π·Π²Π°Π½Π΅. ИзглСТда ΠΊΠ°Ρ‚ΠΎ ΠΏΡ€ΠΈΠΊΠ°Ρ‡Π²Π°Π½Π΅ Π½Π° синтаксис Π½Π° скоби вдясно, ΠΏΠΎ ΡΡŠΡ‰Π΅ΡΡ‚Π²ΠΎ Π·Π°Ρ…Π°Ρ€.

Код

# chaining

res1 <- dt[a == 'a'][sample(.N, 100)]

res2 <- dt[, .N, a][, N]

res3 <- dt[, coefficients(lm(e ~ d))[1], a][, .(letter = a, coef = V1)]

Π’Π΅Ρ‡Π΅ ΠΏΡ€Π΅Π· Ρ‚Ρ€ΡŠΠ±ΠΈΡ‚Π΅...

Π‘ΡŠΡ‰ΠΈΡ‚Π΅ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° сС ΠΈΠ·Π²ΡŠΡ€ΡˆΠ²Π°Ρ‚ Ρ‡Ρ€Π΅Π· Ρ‚Ρ€ΡŠΠ±ΠΎΠΏΡ€ΠΎΠ²ΠΎΠ΄ΠΈ, ΠΈΠ·Π³Π»Π΅ΠΆΠ΄Π° ΠΏΠΎΠ΄ΠΎΠ±Π½ΠΎ, Π½ΠΎ Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»Π½ΠΎ ΠΏΠΎ-Π±ΠΎΠ³Π°Ρ‚ΠΎ, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚Π΅ всякакви ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΈ, Π½Π΅ само DT. НСка ΠΈΠ·Π²Π΅Π΄Π΅ΠΌ ΠΊΠΎΠ΅Ρ„ΠΈΡ†ΠΈΠ΅Π½Ρ‚ΠΈ Π½Π° логистична рСгрСсия Π·Π° Π½Π°ΡˆΠΈΡ‚Π΅ синтСтични Π΄Π°Π½Π½ΠΈ с Ρ€Π΅Π΄ΠΈΡ†Π° Ρ„ΠΈΠ»Ρ‚Ρ€ΠΈ Π½Π° DT.

Код

# piping

samplpe_b <- dt[a %in% head(letters), sample(b, 1)]

res4 <- 
	dt %>%
	.[a %in% head(letters)] %>%
	.[, 
	  {
	  	dt0 <- .SD[1:100]
	  	
	  	quants <- 
	  		dt0[, c] %>%
	  		quantile(seq(0.1, 1, 0.1), na.rm = T)
	  	
	  	.(q = quants)
	  }
	  , .(cond = b > samplpe_b)
	  ] %>%
	glm(
		cond ~ q -1
		, family = binomial(link = "logit")
		, data = .
	) %>%
	summary %>%
	.[[12]]

Бтатистика, машинно ΠΎΠ±ΡƒΡ‡Π΅Π½ΠΈΠ΅ ΠΈ Π΄Ρ€ΡƒΠ³ΠΈ Π² DT

ΠœΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚Π΅ Π»Π°ΠΌΠ±Π΄Π° Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, Π½ΠΎ понякога Π΅ ΠΏΠΎ-Π΄ΠΎΠ±Ρ€Π΅ Π΄Π° Π³ΠΈ ΡΡŠΠ·Π΄Π°Π΄Π΅Ρ‚Π΅ ΠΎΡ‚Π΄Π΅Π»Π½ΠΎ, Π΄Π° Π½Π°ΠΏΠΈΡˆΠ΅Ρ‚Π΅ цСлия Ρ‚Ρ€ΡŠΠ±ΠΎΠΏΡ€ΠΎΠ²ΠΎΠ΄ Π·Π° Π°Π½Π°Π»ΠΈΠ· Π½Π° Π΄Π°Π½Π½ΠΈ ΠΈ Π΄Π°Π²Π°ΠΉΡ‚Π΅ Π½Π°ΠΏΡ€Π΅Π΄ - Ρ‚Π΅ работят Π²ΡŠΡ‚Ρ€Π΅ Π² DT. ΠŸΡ€ΠΈΠΌΠ΅Ρ€ΡŠΡ‚ Π΅ ΠΎΠ±ΠΎΠ³Π°Ρ‚Π΅Π½ с всички горСпосочСни Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, плюс няколко ΠΏΠΎΠ»Π΅Π·Π½ΠΈ Π½Π΅Ρ‰Π° ΠΎΡ‚ арсСнала Π½Π° DT (ΠΊΠ°Ρ‚ΠΎ Π΄ΠΎΡΡ‚ΡŠΠΏ Π΄ΠΎ самия DT Π²ΡŠΡ‚Ρ€Π΅ Π² DT Ρ‡Ρ€Π΅Π· Π²Ρ€ΡŠΠ·ΠΊΠ°, понякога Π²ΠΌΡŠΠΊΠ½Π°Ρ‚Π° Π½Π΅ послСдоватСлно, Π° Ρ‚Π°ΠΊΠ°, Ρ‡Π΅ Π΄Π° Π΅).

Код

# function

rm(lm_preds)

lm_preds <- function(
	sd, by, n
)
{
	
	if(
		n < 100 | 
		!by[['a']] %in% head(letters, 4)
	   )
	{
		
		res <-
			list(
				low = NA
				, mean = NA
				, high = NA
				, coefs = NA
			)
		
	} else {

		lmm <- 
			lm(
				d ~ c + b
				, data = sd
			)
		
		preds <- 
			stats::predict.lm(
				lmm
				, sd
				, interval = "prediction"
				)
		
		res <-
			list(
				low = preds[, 2]
				, mean = preds[, 1]
				, high = preds[, 3]
				, coefs = coefficients(lmm)
			)
	}

	res
	
}

res5 <- 
	dt %>%
	.[e < 0] %>%
	.[.[, .I[b > 0]]] %>%
	.[, `:=` (
		low = as.numeric(lm_preds(.SD, .BY, .N)[[1]])
		, mean = as.numeric(lm_preds(.SD, .BY, .N)[[2]])
		, high = as.numeric(lm_preds(.SD, .BY, .N)[[3]])
		, coef_c = as.numeric(lm_preds(.SD, .BY, .N)[[4]][1])
		, coef_b = as.numeric(lm_preds(.SD, .BY, .N)[[4]][2])
		, coef_int = as.numeric(lm_preds(.SD, .BY, .N)[[4]][3])
	)
	, a
	] %>%
	.[!is.na(mean), -'e', with = F]


# plot

plo <- 
	res5 %>%
	ggplot +
	facet_wrap(~ a) +
	geom_ribbon(
		aes(
			x = c * coef_c + b * coef_b + coef_int
			, ymin = low
			, ymax = high
			, fill = a
		)
		, size = 0.1
		, alpha = 0.1
	) +
	geom_point(
		aes(
			x = c * coef_c + b * coef_b + coef_int
			, y = mean
			, color = a
		)
		, size = 1
	) +
	geom_point(
		aes(
			x = c * coef_c + b * coef_b + coef_int
			, y = d
		)
		, size = 1
		, color = 'black'
	) +
	theme_minimal()

print(plo)

Π—Π°ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅

Надявам сС, Ρ‡Π΅ успях Π΄Π° създам пълна, Π½ΠΎ, Ρ€Π°Π·Π±ΠΈΡ€Π° сС, Π½Π΅ пълна ΠΊΠ°Ρ€Ρ‚ΠΈΠ½Π° Π½Π° Ρ‚Π°ΠΊΡŠΠ² ΠΎΠ±Π΅ΠΊΡ‚ ΠΊΠ°Ρ‚ΠΎ data.table, Π·Π°ΠΏΠΎΡ‡Π²Π°ΠΉΠΊΠΈ ΠΎΡ‚ Π½Π΅Π³ΠΎΠ²ΠΈΡ‚Π΅ свойства, ΡΠ²ΡŠΡ€Π·Π°Π½ΠΈ с наслСдяванС ΠΎΡ‚ R класовС, ΠΈ Π·Π°Π²ΡŠΡ€ΡˆΠ²Π°ΠΉΠΊΠΈ със собствСнитС ΠΌΡƒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΈ срСда ΠΎΡ‚ tidyverse Π΅Π»Π΅ΠΌΠ΅Π½Ρ‚ΠΈ . Надявам сС, Ρ‡Π΅ Ρ‚ΠΎΠ²Π° Ρ‰Π΅ Π²ΠΈ ΠΏΠΎΠΌΠΎΠ³Π½Π΅ Π΄Π° Π½Π°ΡƒΡ‡ΠΈΡ‚Π΅ ΠΏΠΎ-Π΄ΠΎΠ±Ρ€Π΅ ΠΈ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚Π΅ Ρ‚Π°Π·ΠΈ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° Π·Π° Π²Π°ΡˆΠ°Ρ‚Π° Ρ€Π°Π±ΠΎΡ‚Π° ΠΈ Π·Π°Π±Π°Π²Π»Π΅Π½ΠΈΠ΅.

Около data.table

Благодаря Π²ΠΈ!

ПълСн код

Код

## load libs ----------------

library(data.table)
library(ggplot2)
library(magrittr)
library(microbenchmark)


## arrays ---------

arrmatr <- array(1:20, c(4,5))

class(arrmatr)

typeof(arrmatr)

is.array(arrmatr)

is.matrix(arrmatr)


## lists ------------------

mylist <- as.list(arrmatr)

is.vector(mylist)

is.list(mylist)


## data.frames ------------

df <- as.data.frame(arrmatr)

is.list(df)

df$V6 <- df$V1 + df$V2


## data.tables -----------------------

data.table::setDT(df)

is.list(df)

is.data.frame(df)

is.data.table(df)

df2 <- df

df[V1 == 1, V2 := 999]

data.table::fsetdiff(df, df2)

df2 <- data.table::copy(df)

df[V1 == 2, V2 := 999]

data.table::fsetdiff(df, df2)


## operations on data.tables ------------

#using list properties

df$'V1'[1]

df[['V1']]

df[[1]][1]

sapply(df, class)

sapply(df, function(x) sum(is.na(x)))


## Bigger example ----

rown <- 100000

dt <- 
	data.table(
		w = sapply(seq_len(rown), function(x) paste(sample(letters, 3, replace = T), collapse = ' '))
		, a = sample(letters, rown, replace = T)
		, b = runif(rown, -3, 3)
		, c = runif(rown, -3, 3)
		, e = rnorm(rown)
	) %>%
	.[, d := 1 + b + c + rnorm(nrow(.))]

# vectorization

# zero - for loop

microbenchmark({
	for(i in 1:nrow(dt))
		{
		dt[
			i
			, first_l := unlist(strsplit(w, split = ' ', fixed = T))[1]
		]
	}
})

# first

microbenchmark({
	dt[
		, first_l := unlist(strsplit(w, split = ' ', fixed = T))[1]
		, by = 1:nrow(dt)
	   ]
})

# second

first_l_f <- function(sd)
{
	strsplit(sd, split = ' ', fixed = T) %>%
		do.call(rbind, .) %>%
		`[`(,1)
}

dt[, first_l := NULL]

microbenchmark({
	dt[
		, first_l := .(first_l_f(w))
		]
})

# third

first_l_f2 <- function(sd)
{
	strsplit(sd, split = ' ', fixed = T) %>%
		unlist %>%
		matrix(nrow = 3) %>%
		`[`(1,)
}

dt[, first_l := NULL]

microbenchmark({
	dt[
		, first_l := .(first_l_f2(w))
		]
})

# fourth

rown <- 100000

words <-
	sapply(
		seq_len(rown)
		, function(x){
			nwords <- rbinom(1, 10, 0.5)
			paste(
				sapply(
					seq_len(nwords)
					, function(x){
						paste(sample(letters, rbinom(1, 10, 0.5), replace = T), collapse = '')
					}
				)
				, collapse = ' '
			)
		}
	)

dt <- 
	data.table(
		w = words
		, a = sample(letters, rown, replace = T)
		, b = runif(rown, -3, 3)
		, c = runif(rown, -3, 3)
		, e = rnorm(rown)
	) %>%
	.[, d := 1 + b + c + rnorm(nrow(.))]

first_l_f3 <- function(sd, n)
{
	l <- strsplit(sd, split = ' ', fixed = T)
	
	maxl <- max(lengths(l))
	
	sapply(l, "length<-", maxl) %>%
		`[`(n,) %>%
		as.character
}

microbenchmark({
	dt[
		, (paste0('w_', 1:3)) := lapply(1:3, function(x) first_l_f3(w, x))
		]
})

dt[
	, (paste0('w_', 1:3)) := lapply(1:3, function(x) first_l_f3(w, x))
	]


# chaining

res1 <- dt[a == 'a'][sample(.N, 100)]

res2 <- dt[, .N, a][, N]

res3 <- dt[, coefficients(lm(e ~ d))[1], a][, .(letter = a, coef = V1)]

# piping

samplpe_b <- dt[a %in% head(letters), sample(b, 1)]

res4 <- 
	dt %>%
	.[a %in% head(letters)] %>%
	.[, 
	  {
	  	dt0 <- .SD[1:100]
	  	
	  	quants <- 
	  		dt0[, c] %>%
	  		quantile(seq(0.1, 1, 0.1), na.rm = T)
	  	
	  	.(q = quants)
	  }
	  , .(cond = b > samplpe_b)
	  ] %>%
	glm(
		cond ~ q -1
		, family = binomial(link = "logit")
		, data = .
	) %>%
	summary %>%
	.[[12]]


# function

rm(lm_preds)

lm_preds <- function(
	sd, by, n
)
{
	
	if(
		n < 100 | 
		!by[['a']] %in% head(letters, 4)
	   )
	{
		
		res <-
			list(
				low = NA
				, mean = NA
				, high = NA
				, coefs = NA
			)
		
	} else {

		lmm <- 
			lm(
				d ~ c + b
				, data = sd
			)
		
		preds <- 
			stats::predict.lm(
				lmm
				, sd
				, interval = "prediction"
				)
		
		res <-
			list(
				low = preds[, 2]
				, mean = preds[, 1]
				, high = preds[, 3]
				, coefs = coefficients(lmm)
			)
	}

	res
	
}

res5 <- 
	dt %>%
	.[e < 0] %>%
	.[.[, .I[b > 0]]] %>%
	.[, `:=` (
		low = as.numeric(lm_preds(.SD, .BY, .N)[[1]])
		, mean = as.numeric(lm_preds(.SD, .BY, .N)[[2]])
		, high = as.numeric(lm_preds(.SD, .BY, .N)[[3]])
		, coef_c = as.numeric(lm_preds(.SD, .BY, .N)[[4]][1])
		, coef_b = as.numeric(lm_preds(.SD, .BY, .N)[[4]][2])
		, coef_int = as.numeric(lm_preds(.SD, .BY, .N)[[4]][3])
	)
	, a
	] %>%
	.[!is.na(mean), -'e', with = F]


# plot

plo <- 
	res5 %>%
	ggplot +
	facet_wrap(~ a) +
	geom_ribbon(
		aes(
			x = c * coef_c + b * coef_b + coef_int
			, ymin = low
			, ymax = high
			, fill = a
		)
		, size = 0.1
		, alpha = 0.1
	) +
	geom_point(
		aes(
			x = c * coef_c + b * coef_b + coef_int
			, y = mean
			, color = a
		)
		, size = 1
	) +
	geom_point(
		aes(
			x = c * coef_c + b * coef_b + coef_int
			, y = d
		)
		, size = 1
		, color = 'black'
	) +
	theme_minimal()

print(plo)

Π˜Π·Ρ‚ΠΎΡ‡Π½ΠΈΠΊ: www.habr.com

ДобавянС Π½Π° Π½ΠΎΠ² ΠΊΠΎΠΌΠ΅Π½Ρ‚Π°Ρ€