将第一行按组附加到原始数据

ail*_*ail 5 r append data-manipulation

我有带有分组变量“ID”和一些值的数据:

ID, Value
1, 1
1, 2
1, 3
1, 4
2, 5
2, 6 
2, 7
2, 8
Run Code Online (Sandbox Code Playgroud)

在每个组中,我想在最后一行之后附加第一行。期望的结果:

ID, Value
1, 1
1, 2
1, 3
1, 4
1, 1 # First row of ID 1 inserted as last row in the group
2, 5
2, 6 
2, 7
2, 8
2, 5 # First row of ID 2 inserted as last row in the group
Run Code Online (Sandbox Code Playgroud)

我有 5000 行这个。

har*_*rre 5

在 中tidyverse,您可以使用add_rowwith do(现已弃用)或group_modify实验性):

\n
dat |>\n  group_by(ID) |>\n  do(add_row(., ID = unique(.$ID), Value = first(.$Value))) |>\n  ungroup()\n
Run Code Online (Sandbox Code Playgroud)\n
dat |>\n  group_by(ID) |>\n  group_modify(~ add_row(., Value = first(.$Value))) |>\n  ungroup()\n
Run Code Online (Sandbox Code Playgroud)\n

或者bind_rowssummarize(我的@Gregor Thomas的变体,谢谢):

\n
dat |> \n  group_by(ID) |>\n  summarize(bind_rows(cur_data(), head(cur_data(), 1))) |>\n  ungroup()\n
Run Code Online (Sandbox Code Playgroud)\n

或者通过使用 @Henrik 的相同逻辑,使用bind_rowsfilterarrange

\n
dat |> \n  group_by(ID) |>\n  summarize(bind_rows(cur_data(), head(cur_data(), 1))) |>\n  ungroup()\n
Run Code Online (Sandbox Code Playgroud)\n

输出:

\n
dat |>\n  bind_rows(dat |> filter(!duplicated(ID))) |>\n  arrange(ID)\n
Run Code Online (Sandbox Code Playgroud)\n

感谢@SamR 提供的数据。

\n


Sam*_*amR 2

这是一个基本的 R 方法:

do.call(rbind, 
    lapply(split(dat, dat$ID), \(id_df) rbind(id_df, id_df[1,]))
) 
#      ID Value
# 1.1   1     1
# 1.2   1     2
# 1.3   1     3
# 1.4   1     4
# 1.5   1     1
# 2.5   2     5
# 2.6   2     6
# 2.7   2     7
# 2.8   2     8
# 2.51  2     5
Run Code Online (Sandbox Code Playgroud)

它确实给了你稍微奇怪的行名称 - 如果你关心它,你可以将它包装在(或通过管道传输到)中tibble::as_tibble(),这会完全删除行名称。

或者您可以这样做data.table::rbindlist(lapply(split(dat, dat$ID), \(id_df) rbind(id_df, id_df[1,]))),因为data.table也不使用行名称。

数据

dat  <- read.csv(text = "ID, Value
1, 1
1, 2
1, 3
1, 4
2, 5
2, 6 
2, 7
2, 8", h=T)
Run Code Online (Sandbox Code Playgroud)