R:行完成不同标准的向量

时间:2018-06-18 22:41:48

标签: r for-loop dataframe vector

假设我有一个如下所示的数据框event_data

  ID event_one event_two
1  A         1         8
2  B         3         5
3  C         9        13
4  D         9        13
5  E        10        10
6  F        13        15
7  G        13        17
8  H        14        17
9  I        15        19

event列是从某个初始时间0到事件发生所经过的时间量。因此对于对象Cevent_one发生在时间9,event_two发生在时间13。

我想要的是采用times

的向量
> times = 0:20
> times
 [1]  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20

然后浏览两列,了解每次发生的事情。输出应该如下所示:

time    event_ones      event_twos
0       0               0
1       1               0
2       0               0
3       1               0
4       0               0
5       0               1
6       0               0
7       0               0
8       0               1
9       2               0
10      1               1
11      0               0
12      0               0
13      2               2
14      1               0
15      1               1
16      0               0
17      0               2
18      0               0
19      0               1
20      0               0

我意识到我可以通过循环遍历times中的每个元素并迭代地构建表来解决这个问题,但是你真的不应该在R中这样做,我怀疑有更简洁的方法。如果可能的话,它也应该推广到任意多列(我给出的例子是简化的;我的真实数据中有更多这些事件,我必须找到时间计数)。

3 个答案:

答案 0 :(得分:2)

不需要包裹。转换为因子和表:

data.frame(
    time=0:20,
    lapply(
        dat[c("event_one","event_two")],
        function(x) c(table(factor(x, levels=0:20)))
    )
)

不太清楚,您可以使用tabulate

data.frame(time=0:20, lapply(dat[c("event_one","event_two")]+1, tabulate, nbins=21))

答案 1 :(得分:1)

df2   <- rbind(data.frame(event="one",time=df$event_one), 
               data.frame(event="two",time=df$event_two))
times <- data.frame(time=1:20)


library(dplyr)    
library(tidyr)

df <- times %>% 
  left_join(df2, by=c("time" = "time")) %>% 
  group_by(time,event) %>% 
  summarize(count=n()) %>% 
  spread(event, count) %>% 
  replace_na(list(one = 0, two = 0))

print(df[,1:3], row.names=F)
# A tibble: 20 x 3
# Groups:   time [20]
    time   one   two
   <int> <dbl> <dbl>
 1     1    1.    0.
 2     2    0.    0.
 3     3    1.    0.
 4     4    0.    0.
 5     5    0.    1.
 6     6    0.    0.
 7     7    0.    0.
 8     8    0.    1.
 9     9    2.    0.
10    10    1.    1.
11    11    0.    0.
12    12    0.    0.
13    13    2.    2.
14    14    1.    0.
15    15    1.    1.
16    16    0.    0.
17    17    0.    2.
18    18    0.    0.
19    19    0.    1.
20    20    0.    0.

你会注意到print()我索引的列1:3。这只是因为它还创建了第4个“NA”类别列,表示没有事件的时间。你可以放弃它。

答案 2 :(得分:1)

这需要dplyr包。首先,我创建一个虚拟数据框。

# Dummy data frame
df <- data.frame(event_one = sample(1:20, 10, replace = TRUE),
                 event_two = sample(1:20, 10, replace = TRUE))

接下来,我定义一个使用table计算每个事件的函数,并将输出重新打包为数据框。

# Tabulating function
dain_table <- function(foo){
  data.frame(table(foo)) %>% 
    rename(times = foo)
}          

最后,我将函数应用于虚拟数据框中的每一列,并将其连接到所有可能的times

# Package it all together
Reduce(function(x, y)left_join(x, y, by = 'times'), lapply(df, dain_table)) %>% 
  mutate(times = as.numeric(times)) %>% 
  right_join(data.frame(times = 1:20))

#    times Freq.x Freq.y
# 1      1     NA     NA
# 2      2     NA     NA
# 3      3     NA     NA
# 4      4      1     NA
# 5      5     NA     NA
# 6      6     NA     NA
# 7      7     NA     NA
# 8      8      1      1
# 9      9      1     NA
# 10    10      1      1
# 11    11     NA     NA
# 12    12      1     NA
# 13    13      1     NA
# 14    14     NA     NA
# 15    15     NA     NA
# 16    16     NA     NA
# 17    17     NA     NA
# 18    18      2      2
# 19    19      2      1
# 20    20     NA     NA