如果我有以下data.frame:
> df <- data.frame(x = c('a', 'b*', 'c'), y = c('d', 'e', 'f'))
> df
x y
1 a d
2 b* e
3 c f
是否有明确的方法来标识df$x
条目包含字符串值*
的行,然后使用此条件强制将该行的字符串条目与其前面的行合并,产生如下的data.frame:
> df
x y
1 a b* d e
2 c f
我假设问题的第一部分(标识包含`*的x
行值)可以使用正则表达式以相当简单的方式完成。我无法确定如何强制data.frame行与其前面的行合并。
一个特别棘手的挑战是连续多个条目是否具有模式,例如
> df <- data.frame(x = c('a', 'b*', 'c*'), y = c('d', 'e', 'f'))
> df
x y
1 a d
2 b* e
3 c* f
在这种情况下,生成的data.frame应如下所示:
> df
x y
1 a b* c* d e f
我发现的主要问题是,在运行一个循环的迭代后,将df[2,]
的字符串粘贴到df[1,]
,data.frame索引不适应新的data.frame大小:
> df
x y
1 a b* d e
3 c* f
因此,后续索引被中断。
答案 0 :(得分:4)
这是一个初步解决方案:
# Creating the data frame
df <- data.frame(x = c('a', 'b*', 'c'), y = c('d', 'e', 'f'),stringsAsFactors = FALSE)
df
# Creating a vector of rows with *
ast <- grepl("\\*",df$x)
# For loop
for(i in seq(length(ast),1,-1)){
if(ast[i]){
df[i-1,"x"] <- paste(df[i-1,"x"],df[i,"x"],sep=" ")
df[i-1,"y"] <- paste(df[i-1,"y"],df[i,"y"],sep=" ")
df <- df[-i,]
}
}
这是一个初始解决方案,因为您仍需要管理第一行有*以及其他类似情况。我希望这有帮助。
答案 1 :(得分:2)
实际上并没有合并行,但是对于那些具有*的行,它会粘贴前一行的值,然后它会删除在下一行中包含*的行。
library(dplyr)
df <- data.frame(x = c('a', 'b*', 'c'), y = c('d', 'e', 'f'))
df <- mutate(df,
Operator = grepl("\\*",x), # Check for *
lagged.x = lag(x, n = 1), # Get x value from 1 row ago
lagged.y = lag(y, n = 1), # Get y value from 1 row ago
x = ifelse(Operator, paste(lagged.x, x),x), # if there is * paste lagged x
y = ifelse(Operator, paste(lagged.y, y),y), # if there is * paste lagged y
lead.Operator = lead(Operator, n = 1) # Check if next row has a *
)
# keep only rows that had no * in following row and that had no following row (last row)
df <- filter(df, !lead.Operator | is.na(lead.Operator))
# Select just the x and y columns
df <- select(df, x, y)
答案 2 :(得分:2)
以下是3个替代方案(对于基础R一个,我假设x
和y
是字符而不是因素。我还使您的数据更复杂,以涵盖不同的场景)
(有点复杂的数据集)
df <- data.frame(x = c('p','a', 'b*', 'c*', 'd', 'h*', 'j*', 'l*', 'n'),
y = c('r','d', 'e', 'f', 'g', 'i', 'k', 'm', 'o'),
stringsAsFactors = FALSE)
基础R
aggregate(. ~ ID,
transform(df, ID = cumsum(!grepl("*", x, fixed = TRUE))),
paste, collapse = " ")
# ID x y
# 1 1 p r
# 2 2 a b* c* d e f
# 3 3 d h* j* l* g i k m
# 4 4 n o
data.table
library(data.table)
setDT(df)[, lapply(.SD, paste, collapse = " "),
by = .(ID = cumsum(!grepl("*", df[["x"]], fixed = TRUE)))]
# ID x y
# 1: 1 p r
# 2: 2 a b* c* d e f
# 3: 3 d h* j* l* g i k m
# 4: 4 n o
dplyr
library(dplyr)
df %>%
group_by(ID = cumsum(!grepl("*", x, fixed = TRUE))) %>%
summarise_all(funs(paste(., collapse = " ")))
# # A tibble: 4 x 3
# ID x y
# <int> <chr> <chr>
# 1 1 p r
# 2 2 a b* c* d e f
# 3 3 d h* j* l* g i k m
# 4 4 n o