2016-01-11 6 views
2

Вопрос

Этот вопрос содержит 2 части.Повторите определенное значение, разное количество раз в R

Во-первых, У меня есть кадр данных, который содержит некоторые цифры в столбце. Это выглядит примерно так.

> df <- data.frame(sr.no.=c(1,2,3,4,5),num=c(1,0,2,1,0)) 
> View(df) 
    sr.no. num 
    1   1   
    2   0 
    3   2 
    4   1 
    5   0 

Теперь я хочу повторить фиксированное значение (скажем, текст «х») в зависимости от числа в 1-м столбце кадра данных. Если есть несколько повторений, я хочу, чтобы они были разделены пробелом.

Желаемая Выход

> View(df) 
    sr.no. num  rep 
    1   1  x 
    2   0  
    3   2  x x 
    4   1  x 
    5   0 

Я попытался с помощью функции повторений, но она дает некоторые ошибки, и я не в полной мере понять, как работает функция респ. Я думаю, я знаю, что он делает, но не «как» ..

> rep("x",df$num) 
Error in rep("x", df$num) : invalid 'times' argument 
> rep("x",df[df$num]) 
Error: (list) object cannot be coerced to type 'integer' 

ПРИМЕЧАНИЕ: Фактический кадр данных велик, поэтому мы не можем просто создать список «х» вручную.

В настоящее время второй раздел не связан с моей проблемой выше, но это связано только с функцией rep.

Если я пишу это,

> rep(1:2,df$num) 
Error in rep(1:2, df$num) : invalid 'times' argument 

я получаю сообщение об ошибке. Но если я напишу это,

> rep(1:length(df$num),df$num) 
[1] 1 3 3 4 

Получаю вышеуказанный выход. Может кто-то, пожалуйста, объясните мне, во-первых, как решить мою проблему повторения; и затем, как результат, rep дает ошибку в одном случае, а не в другом.

ответ

2

Так как вы сказали, что набор данных довольно велик , использование функции apply может занять время для обработки. Вместо этого вы можете использовать библиотеку (stringi) и функцию stri_dup , и в этом случае вы получите тот же результат, но быстрее.

поэтому используйте

library(stringi) 

cbind(df,rep=stri_dup("x ",df$num)) 

    sr.no. num rep 
1  1 1 x 
2  2 0  
3  3 2 x x 
4  4 1 x 
5  5 0  
+0

thx .... отлично работает –

+0

FYI, вам не нужно использовать 'cbind' здесь. Вы можете сделать 'df $ rep = stri_dup ('x", df $ num) ' – Heroka

2

Try:

> df$rep<-apply(df,1,function(x){ paste(rep("x",x["num"]),collapse=" ")}) 
> df 
    sr.no num rep 
1  1 1 x 
2  2 0 
3  3 2 x x 
4  4 1 x 
5  5 0 

rep(1:2,df$num) потому что df$num имеет 5 номеров, а 1:2 всего 2 номера так rep не имеет ни малейшего представления о том, сколько раз повторять 1: 2.

rep(1:length(df$num),df$num в основном rep(c(1,2,3,4,5),c(1,0,2,1,0)) поэтому он знает, повторить 1 (1 раз), 2 (0 раза), 3 (2 раза), и т.д ...

+0

привет, спасибо за ответ ... он работает, но данные большие, поэтому применение потребует времени. также, спасибо за объяснение функциональности rep –

3

Мы также можем сделать это с помощью data.table. Вы упомянули, что данные большие, и я подозреваю, что многие «nums» появятся в данных несколько раз. Поэтому, создавая каждую строку «rep» только один раз и используя быстрый пакет data.table будет быстрее.

setDT(dat)[,rep:=paste(rep("x",num),collapse=" "),by=num] 
dat 

> dat 
    sr.no. num rep 
1:  1 1 x 
2:  2 0  
3:  3 2 x x 
4:  4 1 x 
5:  5 0  

Из интереса, и потому, что скорость/производительность была озабоченность я провел несколько тестов на наборе данных с миллионами строк.

#creating data 
set.seed(123) 
largedat <- data.frame(sr.no.=1:1e6, num=sample(0:50,1e5, replace=T)) 

Это были (неудивительные) результаты.

Unit: milliseconds 
    expr   min   lq  mean  median   uq   max neval cld 
    heroka 20.49455 25.44678 34.85443 32.00066 44.51929 57.99193 20 a 
    Krrish 206.14323 272.43439 370.22651 377.10149 467.71401 518.09284 20 b 
fishtank 12740.56664 12896.42906 13417.82434 13223.84195 13931.15781 14605.41123 20 c 
+0

thx .... отлично работает –

Смежные вопросы