我有一个与下面的reprex类似的数据帧列表,但是有100列以上:
# reproducible example
df <- data.frame(
Name = c("Name1", "Name2", "Name3", "Name4", "Name5"),
Date = c("2018-01-01", "2018-01-02"),
Value1 = c(rnorm(5, 2, 3), rnorm(5, 4, 1)),
Value2 = c(rnorm(5, 12, 4), rnorm(5, 5, 8)),
Value3 = c(rnorm(5, 22, 13), rnorm(5, 7, 10))
)
# transform data frame into list
df <- split(df, df$Name)
对于列表中的每个数据帧,我想用上一行的值替换最后一行。例如,对于列表中的每个数据框,我想将[2, 3:5]
替换为[1, 3:5]
。
> tail(df[["Name1"]], n = 2)
Name Date Value1 Value2 Value3
1 Name1 2018-01-01 0.9184539 15.658510 29.219707
2 Name1 2018-01-02 3.8875463 3.628546 9.777399
我不确定是否将数据帧转换为列表是执行此操作的最佳方法,因此欢迎其他建议。我尝试解决此问题,如下所述,但我的尝试只是将数据框中的最后一行替换为倒数第二行。
我的尝试
# reproducible example
df <- data.frame(
Name = c("Name1", "Name2", "Name3", "Name4", "Name5"),
Date = c("2018-01-01", "2018-01-02"),
Value1 = c(rnorm(5, 2, 3), rnorm(5, 4, 1)),
Value2 = c(rnorm(5, 12, 4), rnorm(5, 5, 8)),
Value3 = c(rnorm(5, 22, 13), rnorm(5, 7, 10))
)
# arrange by Name and Date
df <- df %>% dplyr::arrange(Name, Date)
# attempt to replace
df[length(df$Name), c(3:5)] <- df[length(df$Name)-1, c(3:5)]
# result
tail(df, n = 4)
> tail(df, n = 4)
Name Date Value1 Value2 Value3
7 Name4 2018-01-01 3.242383 -11.44217 -1.215688
8 Name4 2018-01-02 -4.042093 18.18184 1.544271
9 Name5 2018-01-01 -1.930195 13.18662 18.889372
10 Name5 2018-01-02 -1.930195 13.18662 18.889372
答案 0 :(得分:1)
一个tidyverse
解决方案。我认为没有必要转换为列表。 df
是示例中的数据框。我们可以用NA
替换最后一行,然后使用fill
填充上一行。
library(tidyverse)
df2 <- df %>%
group_by(Name) %>%
mutate_at(vars(starts_with("Value")),
funs(ifelse(row_number() == max(row_number()), NA, .))) %>%
fill(starts_with("Value")) %>%
ungroup()
df2
# # A tibble: 10 x 5
# Name Date Value1 Value2 Value3
# <fct> <fct> <dbl> <dbl> <dbl>
# 1 Name1 2018-01-01 1.35 14.5 34.2
# 2 Name1 2018-01-02 1.35 14.5 34.2
# 3 Name2 2018-01-02 2.42 4.43 19.5
# 4 Name2 2018-01-01 2.42 4.43 19.5
# 5 Name3 2018-01-01 4.60 14.1 15.8
# 6 Name3 2018-01-02 4.60 14.1 15.8
# 7 Name4 2018-01-02 6.36 11.4 9.40
# 8 Name4 2018-01-01 6.36 11.4 9.40
# 9 Name5 2018-01-01 0.214 8.34 33.8
# 10 Name5 2018-01-02 0.214 8.34 33.8
以下内容可能会更好。此命令不使用fill
函数,也不会更改行顺序。
df2 <- df %>%
group_by(Name) %>%
mutate_at(vars(starts_with("Value")),
funs(ifelse(row_number() == max(row_number()),
nth(., n = max(row_number()) - 1),
.))) %>%
ungroup()
df2
# # A tibble: 10 x 5
# Name Date Value1 Value2 Value3
# <fct> <fct> <dbl> <dbl> <dbl>
# 1 Name1 2018-01-01 4.40 13.5 28.0
# 2 Name2 2018-01-02 1.82 8.23 20.9
# 3 Name3 2018-01-01 1.07 16.9 7.50
# 4 Name4 2018-01-02 1.09 8.05 14.4
# 5 Name5 2018-01-01 1.17 11.6 24.0
# 6 Name1 2018-01-02 4.40 13.5 28.0
# 7 Name2 2018-01-01 1.82 8.23 20.9
# 8 Name3 2018-01-02 1.07 16.9 7.50
# 9 Name4 2018-01-01 1.09 8.05 14.4
# 10 Name5 2018-01-02 1.17 11.6 24.0