2016-10-17 14 views
0

В R у меня есть достаточно большой фрейм данных (d), который равен 10500 на 6000. Все значения являются числовыми. У него много элементов значения na в обеих его строках и столбцах, и я хочу заменить эти значения нулем. Я использовал:установить отсутствующие значения в константу в R, вычислительную скорость

d[is.na(d)] <- 0

, но это довольно медленно. Есть ли лучший способ сделать это в R?

Я открыт для использования других пакетов R.

Я бы предпочел, чтобы обсуждение было сосредоточено на вычислительной скорости, а не на «почему бы вы заменили na на нули», например. И, хотя я понимаю, что аналогичный Q был задан (How do I replace NA values with zeros in an R dataframe?), фокус не был связан с вычислительной скоростью на большом кадре данных со многими отсутствующими значениями.

Спасибо!

Edited Решение: Как услужливо предложил, изменение д к матрице перед применением is.na ускорил вычисление по порядку величины

+4

ли этот фрейм данных столбцов одного и того же типа (т.е. все числовые, или все характера)? Хранение его в виде матрицы может ускорить это. – Spacedman

+1

частое преобразование в 'data.table' обеспечивает улучшение скорости для многих операций, но' is.na.data.table' не является одним из них. – shayaa

+0

@ Spacedman, все числовые - извините, должен был указать это. будет редактировать. – Peter

ответ

1

Я думаю, что все столбцы должны быть числовым или назначая 0s к ВПЛ не было бы разумным.

я получаю следующие моменты времени, с примерно 10000 ВПЛ:

> M <- matrix(0, 10500, 6000) 
> set.seed(54321) 
> r <- sample(1:10500, 10000, replace=TRUE) 
> c <- sample(1:6000, 10000, replace=TRUE) 
> M[cbind(r, c)] <- NA 
> D <- data.frame(M) 
> sum(is.na(M)) # check 
[1] 9999 
> sum(is.na(D)) # check 
[1] 9999 
> system.time(M[is.na(M)] <- 0) 
    user system elapsed 
    0.19 0.12 0.31 
> system.time(D[is.na(D)] <- 0) 
    user system elapsed 
    3.87 0.06 3.95 

Таким образом, с этим числом ВПЛ, я о порядке величины ускорения, используя матрицу. (С меньшим количеством НС разница меньше). Но время, использующее фрейм данных, всего лишь 4 секунды на моем скромном ноутбуке - намного меньше времени, чем потребовалось, чтобы ответить на вопрос. Если проблема действительно имеет такую ​​величину, почему это медленно?

Надеюсь, это поможет.

+0

Я зацикливаю несколько сотен таких данных data.frames, некоторые из которых намного больше, поэтому ускорение скорости имеет практическую значимость. Спасибо за ответ. – Peter

1

Вы можете получить значительное увеличение производительности с помощью пакета data.table. Это намного быстрее, в общем, с большим количеством манипуляций и преобразований. Недостатком является кривая обучения синтаксиса. Однако, если вы ищете повышение скорости, инвестиции могут стоить того.

Сформировать поддельные данные

r <- 10500 
c <- 6000 
x <- sample(c(NA, 1:5), r * c, replace = TRUE) 
df <- data.frame(matrix(x, nrow = r, ncol = c)) 

Base R

df1 <- df 
system.time(df1[is.na(df1)] <- 0) 

    user system elapsed 
    4.74 0.00 4.78 

tidyr - replace_na()

dfReplaceNA <- function (df) { 
    require(tidyr) 
    l <- setNames(lapply(vector("list", ncol(df)), function(x) x <- 0), names(df)) 
    replace_na(df, l) 
} 
system.time(df2 <- dfReplaceNA(df)) 

    user system elapsed 
    4.27 0.00 4.28 

данные.стол - set()

dtReplaceNA <- function (df) { 
    require(data.table) 
    dt <- data.table(df) 
    for (j in 1:ncol(dt)) {set(dt, which(is.na(dt[[j]])), j, 0)} 
    setDF(dt) # Return back a data.frame object 
} 
system.time(df3 <- dtReplaceNA(df)) 

    user system elapsed 
    0.80 0.31 1.11 

Сравнить кадры данных

all.equal(df1, df2) 

[1] TRUE 

all.equal(df1, df3) 

[1] TRUE