我正在尝试在R中实现以下目标,而不使用嵌套的for循环:
input_df: output_df:
Attr1 Attr2 Dates Attr1 Attr2 StartDate EndDate
1 2 A-B,B-C,D-E 1 2 A B
3 4 F-G --> 1 2 B C
5 6 H-I,J-K 1 2 D E
3 4 F G
5 6 H I
5 6 J K
数据框有50,000多行,for循环要花很长时间才能完成工作。
答案 0 :(得分:2)
使用基数R,您可以执行以下操作。用“,”分隔“日期”列,然后在“-”上再次分隔结果以创建一个两列的数据框。
d <- strsplit(input_df$Dates, ',')
x <- do.call(rbind, strsplit(unlist(d), '-'))
现在,您可以重复原始数据的Attr1,Attr2字段,并重复所产生的','分割的分量:
data.frame(input_df[rep(seq_len(NROW(input_df)), lengths(d)), 1:2],
Start = x[,1],
End = x[, 2])
# output
# Attr1 Attr2 Start End
#1 1 2 A B
#1.1 1 2 B C
#1.2 1 2 D E
#2 3 4 F G
#3 5 6 H I
#3.1 5 6 J K
其中input_df的定义如下:
input_df <- data.frame(Attr1 = c(1L, 3L, 5L),
Attr2 = c(2L, 4L, 6L),
Dates = c("A-B,B-C,D-E", "F-G", "H-I,J-K"),
stringsAsFactors = FALSE)
答案 1 :(得分:1)
我们可以将separate_rows
与separate
一起使用。在定界符,
处分割'日期'列,并用separate_rows
展开行,然后用separate
在定界符-
处将'日期'分为两列< / p>
library(tidyr)
library(dplyr)
separate_rows(input_df, Dates, sep = ",") %>%
separate(Dates, into = c("StartDate", "EndDate"))
# Attr1 Attr2 StartDate EndDate
#1 1 2 A B
#2 1 2 B C
#3 1 2 D E
#4 3 4 F G
#5 5 6 H I
#6 5 6 J K
或者另一种选择是将元素提取到list
列中,然后unnest
列在list
列中
library(stringr)
input_df %>%
transmute(Attr1, Attr2,
StartDate = str_extract_all(Dates, "\\w+(?=-)"),
EndDate = str_extract_all(Dates, "(?<=-)\\w+")) %>%
unnest(c(StartDate, EndDate))
input_df <- structure(list(Attr1 = c(1L, 3L, 5L), Attr2 = c(2L, 4L, 6L),
Dates = c("A-B,B-C,D-E", "F-G", "H-I,J-K")),
class = "data.frame", row.names = c(NA,
-3L))
答案 2 :(得分:1)
您可以尝试以下代码,其中substring
用于提取第三列中的对:
res <- Reduce(rbind,
lapply(split(input_df,seq(nrow(input_df))), function(v) {
l <- nchar(v[3])
data.frame(v[-3],
StartDate = substring(v[3],seq(1,l,4),seq(1,l,4)),
EndDate = substring(v[3],seq(3,l,4),seq(3,l,4)),
row.names = NULL)}
)
)
输出
> res
Attr1 Attr2 StartDate EndDate
1 1 2 A B
2 1 2 B C
3 1 2 D E
4 3 4 F G
5 5 6 H I
6 5 6 J K
答案 3 :(得分:0)
我们可以使用cSplit
中的splitstackshape
,首先获取长格式然后宽格式的数据。
library(splitstackshape)
cSplit(cSplit(df, "Dates", direction = "long"), "Dates", sep = "-")
# Attr1 Attr2 Dates_1 Dates_2
#1: 1 2 A B
#2: 1 2 B C
#3: 1 2 D E
#4: 3 4 F G
#5: 5 6 H I
#6: 5 6 J K
数据
df <- structure(list(Attr1 = c(1L, 3L, 5L), Attr2 = c(2L, 4L, 6L),
Dates = structure(1:3, .Label = c("A-B,B-C,D-E", "F-G", "H-I,J-K"
), class = "factor")), class = "data.frame", row.names = c(NA, -3L))