Powtórz każdy wiersz danych.ramka ilość razy określona w kolumnie
df <- data.frame(var1 = c('a', 'b', 'c'), var2 = c('d', 'e', 'f'),
freq = 1:3)
Jaki jest najprostszy sposób na rozwinięcie każdego wiersza dwóch pierwszych kolumn danych.ramka powyżej, tak aby każdy wiersz był powtarzany ilość razy określoną w kolumnie 'freq'?
Innymi słowy, przejdź od tego:
df
var1 var2 freq
1 a d 1
2 b e 2
3 c f 3
Do tego:
df.expanded
var1 var2
1 a d
2 b e
3 b e
4 c f
5 c f
6 c f
9 answers
Oto jedno rozwiązanie:
df.expanded <- df[rep(row.names(df), df$freq), 1:2]
Wynik:
var1 var2
1 a d
2 b e
2.1 b e
3 c f
3.1 c f
3.2 c f
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-24 05:01:19
Stare pytanie, nowy czasownik w tidyverse:
library(tidyr) # version >= 0.8.0
df <- data.frame(var1=c('a', 'b', 'c'), var2=c('d', 'e', 'f'), freq=1:3)
df %>%
uncount(freq)
var1 var2
1 a d
2 b e
2.1 b e
3 c f
3.1 c f
3.2 c f
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-18 03:36:38
Użyj expandRows()
z opakowania splitstackshape
:
library(splitstackshape)
expandRows(df, "freq")
Prosta składnia, bardzo szybka, działa na data.frame
lub data.table
.
Wynik:
var1 var2
1 a d
2 b e
2.1 b e
3 c f
3.1 c f
3.2 c f
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-26 17:11:41
@ neilfws rozwiązanie działa świetnie dla data.frame
s, ale nie dla data.table
S, ponieważ brakuje im właściwości row.names
. To podejście działa zarówno dla:
df.expanded <- df[rep(seq(nrow(df)), df$freq), 1:2]
Kod dla {[3] } jest tad cleaner:
# convert to data.table by reference
setDT(df)
df.expanded <- df[rep(seq(.N), freq), !"freq"]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-05 10:46:38
W przypadku, gdy trzeba wykonać tę operację na bardzo dużych danych.ramki polecam przekonwertować na dane.tabelę i użyj następującej, która powinna działać znacznie szybciej:
library(data.table)
dt <- data.table(df)
dt.expanded <- dt[ ,list(freq=rep(1,freq)),by=c("var1","var2")]
dt.expanded[ ,freq := NULL]
dt.expanded
Zobacz, o ile szybsze jest to rozwiązanie:
df <- data.frame(var1=1:2e3, var2=1:2e3, freq=1:2e3)
system.time(df.exp <- df[rep(row.names(df), df$freq), 1:2])
## user system elapsed
## 4.57 0.00 4.56
dt <- data.table(df)
system.time(dt.expanded <- dt[ ,list(freq=rep(1,freq)),by=c("var1","var2")])
## user system elapsed
## 0.05 0.01 0.06
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-07 16:51:04
Kolejna dplyr
alternatywa z slice
gdzie powtarzamy każdy numer wiersza freq
razy
library(dplyr)
df %>%
slice(rep(seq_len(n()), freq)) %>%
select(-freq)
# var1 var2
#1 a d
#2 b e
#3 b e
#4 c f
#5 c f
#6 c f
seq_len(n())
część można zastąpić dowolną z poniższych.
df %>% slice(rep(1:nrow(df), freq)) %>% select(-freq)
#Or
df %>% slice(rep(row_number(), freq)) %>% select(-freq)
#Or
df %>% slice(rep(seq_len(nrow(.)), freq)) %>% select(-freq)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-07-08 06:20:00
Inną możliwością jest użycie tidyr::expand
:
library(dplyr)
library(tidyr)
df %>% group_by_at(vars(-freq)) %>% expand(temp = 1:freq) %>% select(-temp)
#> # A tibble: 6 x 2
#> # Groups: var1, var2 [3]
#> var1 var2
#> <fct> <fct>
#> 1 a d
#> 2 b e
#> 3 b e
#> 4 c f
#> 5 c f
#> 6 c f
Wersja jednowarstwowa odpowiedź vonjd:
library(data.table)
setDT(df)[ ,list(freq=rep(1,freq)),by=c("var1","var2")][ ,freq := NULL][]
#> var1 var2
#> 1: a d
#> 2: b e
#> 3: b e
#> 4: c f
#> 5: c f
#> 6: c f
strona korzysta z plików cookies w celu realizacji usług i zgodnie z Polityką Plików Cookies..2.1)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-05-21 20:14:25
Wiem, że tak nie jest, ale jeśli chcesz zachować oryginalną kolumnę freq, możesz użyć innego podejścia tidyverse
razem z rep
:
library(purrr)
df <- data.frame(var1 = c('a', 'b', 'c'), var2 = c('d', 'e', 'f'), freq = 1:3)
df %>%
map_df(., rep, .$freq)
#> # A tibble: 6 x 3
#> var1 var2 freq
#> <fct> <fct> <int>
#> 1 a d 1
#> 2 b e 2
#> 3 b e 2
#> 4 c f 3
#> 5 c f 3
#> 6 c f 3
strona korzysta z plików cookies w celu realizacji usług i zgodnie z Polityką Plików Cookies..3.0)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-05-08 20:46:29
W rzeczywistości. użyj metod wektor i indeks. możemy również osiągnąć ten sam wynik i łatwiej zrozumieć:
rawdata <- data.frame('time' = 1:3,
'x1' = 4:6,
'x2' = 7:9,
'x3' = 10:12)
rawdata[rep(1, time=2), ] %>% remove_rownames()
# time x1 x2 x3
# 1 1 4 7 10
# 2 1 4 7 10
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-12-02 05:54:48