R使用来自第二个tibble的数据作为行和列更新一个tibble
R update a tibble using data from a second tibble as row and column
我有一个充满 NA 的空标题,其中包含行和列,分别以 ID 号和一段时间内的所有日期命名。例如,这段代码:
tbl <- tibble(PERSONAL_ID = c("A", "B", "C", "D"))
dates = as.character((seq(as.Date("2016-01-01"), as.Date("2016-01-05"), by="days")))
tbl[dates] <- NA
tbl <- column_to_rownames(tbl, var = "PERSONAL_ID")
我有第二个 tibble,其中包含将一个 ID 号与一个日期匹配的列,如本例所示:
enrollments <- tibble(ID = c("D", "B", "C", "D"),
date = c("2016-01-01", "2016-01-03", "2016-01-05", "2016-01-02"))
我想做的是将“1”添加到与第二个标题(注册)中列出的 ID 和日期相对应的第一个标题 (tbl) 的行和列。对于上面的示例代码,所需的输出将是:
2016-01-01 2016-01-02 2016-01-03 2016-01-04 2016-01-05
A <NA> <NA> <NA> <NA> <NA>
B <NA> <NA> 1 <NA> <NA>
C <NA> <NA> <NA> <NA> 1
D 1 1 <NA> <NA> <NA>
谢谢!
这是一个 tidyverse
方法。
- 首先将您的
tbl
从 wide
格式更改为 long
格式,使其与 enrollments
. 的格式匹配
- 在
enrollments
中创建一个 Count
列,每一行都是 Count = 1
。
- 然后
left_join
转换后的 tbl
和 enrollments
使用 ID
和 date
作为连接字段。
- 最后,将
long
格式转换回 wide
格式并设置 rownames
。
library(tidyverse)
left_join(tbl %>% rownames_to_column(var = "ID") %>%
pivot_longer(-ID, names_to = "date", values_to = "Count") %>%
select(-Count),
enrollments %>% mutate(Count = 1),
by = c("ID", "date")) %>%
pivot_wider(names_from = "date", values_from = "Count") %>%
column_to_rownames(var = "ID")
输出
2016-01-01 2016-01-02 2016-01-03 2016-01-04 2016-01-05
A NA NA NA NA NA
B NA NA 1 NA NA
C NA NA NA NA 1
D 1 1 NA NA NA
您的数据集作为参考
tbl
2016-01-01 2016-01-02 2016-01-03 2016-01-04 2016-01-05
A NA NA NA NA NA
B NA NA NA NA NA
C NA NA NA NA NA
D NA NA NA NA NA
enrollments
# A tibble: 4 x 2
ID date
<chr> <chr>
1 D 2016-01-01
2 B 2016-01-03
3 C 2016-01-05
4 D 2016-01-02
这是一个基本的 R 方法。对于注册,我将每一行的 date
和 ID
组合成一个字符串。然后,对于 tbl
,我创建了一个用日期和行名填充的 table。然后,我使用 match
将 enrollment
中的值与 tbl
中的值相匹配。我使用 arrayInd
来获取列和行索引。最后,我 replace
tbl
中的 NA
值和 1
用于提取的 column-row 索引。
replace(tbl, arrayInd(match(do.call(
paste, subset(enrollments, select = c("date", "ID"))),
t(outer(colnames(tbl), rownames(tbl), FUN = paste)
)), .dim = dim(tbl)), 1)
这里有一个稍微不同的 tidyverse
方法,使用 rows_update
。在这里,我将 enrollments
转换为宽格式,然后绑定到 tbl
(但没有行)以便具有相同的列。然后,我使用 enrollments
.
中的新格式更新 tbl
中的行
library(tidyverse)
rows_update(tbl %>% rownames_to_column("ID"), enrollments %>%
mutate(value = 1) %>%
pivot_wider(names_from = "date", values_from = "value") %>%
bind_rows(tbl[0,])) %>%
column_to_rownames("ID")
输出
2016-01-01 2016-01-02 2016-01-03 2016-01-04 2016-01-05
A NA NA NA NA NA
B NA NA 1 NA NA
C NA NA NA NA 1
D 1 1 NA NA NA
这是一个 data.table 方法,使用 PERSONAL_IDS
、dates
和 enrollments
dcast(rbind(
rbindlist(lapply(setdiff(PERSONAL_ID,enrollments$ID), \(x) data.table(ID=x, date=dates)))[,value:=NA],
enrollments[,value:=1]
), ID~date,value.var="value")
输出:
ID 2016-01-01 2016-01-02 2016-01-03 2016-01-04 2016-01-05
1: A NA NA NA NA NA
2: B NA NA 1 NA NA
3: C NA NA NA NA 1
4: D 1 1 NA NA NA
我有一个充满 NA 的空标题,其中包含行和列,分别以 ID 号和一段时间内的所有日期命名。例如,这段代码:
tbl <- tibble(PERSONAL_ID = c("A", "B", "C", "D"))
dates = as.character((seq(as.Date("2016-01-01"), as.Date("2016-01-05"), by="days")))
tbl[dates] <- NA
tbl <- column_to_rownames(tbl, var = "PERSONAL_ID")
我有第二个 tibble,其中包含将一个 ID 号与一个日期匹配的列,如本例所示:
enrollments <- tibble(ID = c("D", "B", "C", "D"),
date = c("2016-01-01", "2016-01-03", "2016-01-05", "2016-01-02"))
我想做的是将“1”添加到与第二个标题(注册)中列出的 ID 和日期相对应的第一个标题 (tbl) 的行和列。对于上面的示例代码,所需的输出将是:
2016-01-01 2016-01-02 2016-01-03 2016-01-04 2016-01-05
A <NA> <NA> <NA> <NA> <NA>
B <NA> <NA> 1 <NA> <NA>
C <NA> <NA> <NA> <NA> 1
D 1 1 <NA> <NA> <NA>
谢谢!
这是一个 tidyverse
方法。
- 首先将您的
tbl
从wide
格式更改为long
格式,使其与enrollments
. 的格式匹配
- 在
enrollments
中创建一个Count
列,每一行都是Count = 1
。 - 然后
left_join
转换后的tbl
和enrollments
使用ID
和date
作为连接字段。 - 最后,将
long
格式转换回wide
格式并设置rownames
。
library(tidyverse)
left_join(tbl %>% rownames_to_column(var = "ID") %>%
pivot_longer(-ID, names_to = "date", values_to = "Count") %>%
select(-Count),
enrollments %>% mutate(Count = 1),
by = c("ID", "date")) %>%
pivot_wider(names_from = "date", values_from = "Count") %>%
column_to_rownames(var = "ID")
输出
2016-01-01 2016-01-02 2016-01-03 2016-01-04 2016-01-05
A NA NA NA NA NA
B NA NA 1 NA NA
C NA NA NA NA 1
D 1 1 NA NA NA
您的数据集作为参考
tbl
2016-01-01 2016-01-02 2016-01-03 2016-01-04 2016-01-05
A NA NA NA NA NA
B NA NA NA NA NA
C NA NA NA NA NA
D NA NA NA NA NA
enrollments
# A tibble: 4 x 2
ID date
<chr> <chr>
1 D 2016-01-01
2 B 2016-01-03
3 C 2016-01-05
4 D 2016-01-02
这是一个基本的 R 方法。对于注册,我将每一行的 date
和 ID
组合成一个字符串。然后,对于 tbl
,我创建了一个用日期和行名填充的 table。然后,我使用 match
将 enrollment
中的值与 tbl
中的值相匹配。我使用 arrayInd
来获取列和行索引。最后,我 replace
tbl
中的 NA
值和 1
用于提取的 column-row 索引。
replace(tbl, arrayInd(match(do.call(
paste, subset(enrollments, select = c("date", "ID"))),
t(outer(colnames(tbl), rownames(tbl), FUN = paste)
)), .dim = dim(tbl)), 1)
这里有一个稍微不同的 tidyverse
方法,使用 rows_update
。在这里,我将 enrollments
转换为宽格式,然后绑定到 tbl
(但没有行)以便具有相同的列。然后,我使用 enrollments
.
tbl
中的行
library(tidyverse)
rows_update(tbl %>% rownames_to_column("ID"), enrollments %>%
mutate(value = 1) %>%
pivot_wider(names_from = "date", values_from = "value") %>%
bind_rows(tbl[0,])) %>%
column_to_rownames("ID")
输出
2016-01-01 2016-01-02 2016-01-03 2016-01-04 2016-01-05
A NA NA NA NA NA
B NA NA 1 NA NA
C NA NA NA NA 1
D 1 1 NA NA NA
这是一个 data.table 方法,使用 PERSONAL_IDS
、dates
和 enrollments
dcast(rbind(
rbindlist(lapply(setdiff(PERSONAL_ID,enrollments$ID), \(x) data.table(ID=x, date=dates)))[,value:=NA],
enrollments[,value:=1]
), ID~date,value.var="value")
输出:
ID 2016-01-01 2016-01-02 2016-01-03 2016-01-04 2016-01-05
1: A NA NA NA NA NA
2: B NA NA 1 NA NA
3: C NA NA NA NA 1
4: D 1 1 NA NA NA