我有一个数据帧,其中某些行是其他几行的后续操作(彼此完成),我想将它们合并成一行。请看下面的例子
+-------+-------------+-----------+-----+---------+
| rowID | name | address | age | firstId |
+-------+-------------+-----------+-----+---------+
| 1 | Bert | | 60 | |
+-------+-------------+-----------+-----+---------+
| 2 | Ernie | Berlin | 72 | |
+-------+-------------+-----------+-----+---------+
| 3 | Bert Sesame | Amsterdam | | 1 |
+-------+-------------+-----------+-----+---------+
第三个rowId指向第一个RowId,这反过来又会使Bert变老60岁。同时,第二行没有firstId(需要跟进的行),应保留原样。
两行中都可以填写一些列,我想填写firstID字段已填写的行(因此是最新行)。例如,第三行的名称为“ Bert Sesame”,在这种情况下,我想使用名称“ bert sesame”,即具有firstId值的行。
最终数据帧为
+-------+-------------+-----------+-----+---------+
| rowID | name | address | age | firstId |
+-------+-------------+-----------+-----+---------+
| 2 | Ernie | Berlin | 72 | |
+-------+-------------+-----------+-----+---------+
| 3 | Bert Sesame | Amsterdam | 60 | 1 |
+-------+-------------+-----------+-----+---------+
我该如何实现?
我看过这样的问题。 Merge two rows in data.frame
但这是通过将所有行分组在一起来指代所有行。我只想合并/合并专门引用其他行的行。
答案 0 :(得分:0)
这里尝试使用tidyverse
。
library(tidyverse)
df %>%
group_by(rowID_new = replace(rowID, firstId != '', firstId[firstId != ''])) %>%
mutate(age = replace(age, age == '', age[age != ''])) %>%
ungroup() %>%
filter(!rowID %in% firstId) %>%
select(-rowID_new)
给出,
# A tibble: 2 x 5 rowID name address age firstId <dbl> <chr> <chr> <chr> <chr> 1 2 B E 72 "" 2 3 C F 60 1
编辑:
如果您要填充多个变量,我们可以将''
替换为NA
并使用fill
,即
df %>%
mutate_all(function(i) replace(i, i == '', NA)) %>%
group_by(rowID_new = replace(rowID, !is.na(firstId), firstId[!is.na(firstId)])) %>%
fill(-rowID, .direction = 'up') %>% #you might not need this[with .direction = 'up']
fill(-rowID) %>%
ungroup() %>%
filter(!rowID %in% firstId)
给出,
# A tibble: 2 x 6 rowID name address age firstId rowID_new <dbl> <chr> <chr> <chr> <chr> <chr> 1 3 C F 60 1 1 2 2 B E 72 <NA> 2
已使用示例
structure(list(rowID = c(1, 2, 3), name = c("A", "B", "C"), address = c("D",
"E", "F"), age = c("60", "72", ""), firstId = c("", "", "1")), class = "data.frame", row.names = c(NA,
-3L))