Как взять 2 столбца, чтобы сгенерировать последовательность длины N и добавить в качестве столбцов в R? - PullRequest
0 голосов
/ 15 апреля 2020

У меня есть фрейм данных с 2 столбцами мин и макс. Я хотел создать последовательность ч / б этих чисел для каждой строки.

df <- data.table("ID"=c("A","B","C"),
                 "mn" = c(1,2,3),
                 "mx" = c(10,5,10)
                 )
> df
    ID mn mx
 1:  A  1  10
 2:  B  2  5
 3:  C  3  10

Я хочу взять эти 2 столбца и сгенерировать 4 порядковых номера для каждой строки

>df
 ID | mn | mx | S1 | s2    | S3 |  s4
  A    1   10    1     4     7      10
  B    2   5     2     3     4      5
  C    3   10    3     5.33  7.66   10 

Я могу повторять над строками и используйте seq (mn, mx, length = N), но я хочу применить эту операцию к 1 миллиону строк, пожалуйста, предложите эффективное решение.

Ответы [ 5 ]

2 голосов
/ 15 апреля 2020

Еще одна векторизованная опция, использующая data.table, которая должна быть быстрее без прохождения строки за строкой:

df[, paste0("s", 1L:4L) := {
        d <- (mx - mn) / 3
        .(mn, mn + d, mn + 2*d, mx)
    }]

В общем, thelatemail предложил:

N <- 4L
df[, paste0("s", seq(N)) := transpose(Map(`+`, mn, 
    lapply((mx - mn) / (N-1), `*`, seq(0, N-1))
))]

Или эквивалентно, но длиннее, но я думаю, что это будет быстрее:

N <- 4L #assuming N >= 2
d <- df[, (mx - mn) / (N - 1)]
init <- df[["mn"]]
for (n in 1L:N) {
    set(df, j=paste0("s", n), value=init + (n-1) * d)
}
1 голос
/ 15 апреля 2020

In data.table , l oop over mn и mx с Map, а затем transpose и назначение :=:

df[, paste0("s", seq(4)) := transpose(Map(seq, mn, mx, length.out=4))]
df
#   ID mn mx s1       s2       s3 s4
#1:  A  1 10  1 4.000000 7.000000 10
#2:  B  2  5  2 3.000000 4.000000  5
#3:  C  3 10  3 5.333333 7.666667 10
1 голос
/ 15 апреля 2020

Один dplyr и tidyr может быть решением:

df %>%
 rowwise() %>%
 mutate(cols = list(mn:mx)) %>%
 unnest_wider(cols) %>%
 rename_at(vars(-mn, -mx), ~ paste0("s", 1:length(.)))

     mn    mx    s1    s2    s3    s4
  <dbl> <dbl> <int> <int> <int> <int>
1     1     4     1     2     3     4
2     2     5     2     3     4     5
3     3     6     3     4     5     6

Или:

df %>%
 mutate(cols = Map(`:`, mn, mx)) %>%
 unnest_wider(cols) %>%
 rename_at(vars(-mn, -mx), ~ paste0("s", 1:length(.)))
1 голос
/ 15 апреля 2020

В одну сторону, используя apply:

cbind(df, t(apply(df, 1, function(x) x[1]:x[2])))

#   mn mx V1 V2 V3 V4
#1:  1  4  1  2  3  4
#2:  2  5  2  3  4  5
#3:  3  6  3  4  5  6

Или mapply:

cbind(df, t(mapply(`:`, df$mn, df$mx)))
0 голосов
/ 15 апреля 2020

Мы можем использовать map2

library(dplyr)
library(purrr)
library(tidyr)
df %>%
     mutate(cols = map2(mn, mx, `:`)) %>%
     unnest_wider(cols)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...