Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R将行分隔为“开始”和“结束”指定的列_R_Dplyr_Tidyr_Read.fwf - Fatal编程技术网

R将行分隔为“开始”和“结束”指定的列

R将行分隔为“开始”和“结束”指定的列,r,dplyr,tidyr,read.fwf,R,Dplyr,Tidyr,Read.fwf,我想将由字符串组成的数据集拆分为由start和end指定的列 我的数据集如下所示: >head(templines,3) [1] "201801 1 78" [2] "201801 2 67" [3] "201801 1 13" 我想通过使用数据字典指定我的列来拆分它: >dictionary col_name col_start col_end year 1 4 week 5 6 gender 8

我想将由字符串组成的数据集拆分为由start和end指定的列

我的数据集如下所示:

>head(templines,3)
[1] "201801 1  78"
[2] "201801 2  67"
[3] "201801 1  13"
我想通过使用数据字典指定我的列来拆分它:

>dictionary
col_name col_start col_end  
year      1         4  
week      5         6  
gender    8         8  
age       11        12  
因此,它变成:

year    week    gender    age
2018    01      1         78
2018    01      2         67
2018    01      1         13
事实上,数据来自一项长期调查,某些列之间的空白代表不再收集的变量。它有很多变量,所以我需要一个可以扩展的解决方案

tidyr::separate
中,似乎只能通过指定要拆分的位置,而不是开始和结束位置进行拆分。有没有一种使用开始/结束的方法

我想用
read_fwf
来实现这一点,但我似乎无法在已经加载的数据集上使用它。我只是通过先将其导出为txt,然后从这个.txt中读取来实现它:

write_lines(templines,"t1.txt")

read_fwf("t1.txt", 
     fwf_positions(start = dictionary$col_start,
                   end = dictionary$col_end,
                   col_names = dictionary$col_name)
可以在已加载的数据集上使用
read\u fwf
吗?

这个怎么样

data.frame(year=substr(templines,1,4), 
           week=substr(templines,5,6), 
           gender=substr(templines,7,8), 
           age=substr(templines,11,13))

这是一个显式函数,它似乎按照您想要的方式工作

split_func<-function(char,ref,name,start,end){
  res<-data.table("ID" = 1:length(char))
  for(i in 1:nrow(ref)){
    res[,ref[[name]][i] := substr(x = char,start = ref[[start]][i],stop = ref[[end]][i])]
  }
  return(res)
}
我必须包含一个“ID”列来启动数据表,使之更容易。如果您想稍后删除它,您可以使用:

out[,ID := NULL]
希望这更接近您所寻找的解决方案。

使用base R:

m = list(`attr<-`(dat$col_start,"match.length",dat$col_end-dat$col_start+1))

d = do.call(rbind,regmatches(x,rep(m,length(x))))

setNames(data.frame(d),dat$col_name)

  year week gender age
1 2018   01      1  78
2 2018   01      2  67
3 2018   01      1  13

带有
子字符串的解决方案

library(data.table)
x <- transpose(lapply(templines, substring, dictionary$col_start, dictionary$col_end))
setDT(x)
setnames(x, dictionary$col_name)
# > x
#    year week gender age
# 1: 2018   01      1  78
# 2: 2018   01      2  67
# 3: 2018   01      1  13
库(data.table)
x x
#年周性别年龄
# 1: 2018   01      1  78
# 2: 2018   01      2  67
# 3: 2018   01      1  13

直接回答您的问题:是的,可以对已加载的数据使用
read_fwf
。文档的相关部分是关于参数
文件的部分

Either a path to a file, a connection, or literal data (either a single string or a raw vector).
...
Literal data is most useful for examples and tests. 
It must contain at least one new line to be recognised as data (instead of a path).
因此,您可以简单地折叠数据,然后使用
read\u fwf

templines %>% 
  paste(collapse = "\n") %>% 
  read_fwf(., fwf_positions(start = dictionary$col_start,
                            end = dictionary$col_end,
                            col_names = dictionary$col_name))
这应该可以扩展到多个列,并且对于许多行来说速度很快(在我的机器上,大约半秒钟可以扩展到100万行和四列)


有一些关于解析失败的警告,但它们来自您的字典。如果您将最后一行更改为
age,11,12
,它将按预期工作。

我们可以使用
tidyverse

library(tidyverse)
data.frame(Col = templines) %>% 
      separate(Col, into = dictionary$col_name, sep= head(dictionary$col_end, -1))
#  year week gender  age
#1 2018   01      1   78
#2 2018   01      2   67
#3 2018   01      1   13

convert=TRUE
参数也可以与
separate
一起使用,以将数字列作为输出

tibble(Col = templines) %>% 
   separate(Col, into = dictionary$col_name, 
       sep= head(dictionary$col_end, -1), convert = TRUE)
# A tibble: 3 x 4
#   year  week gender   age
#  <int> <int>  <int> <int>
#1  2018     1      1    78
#2  2018     1      2    67
#3  2018     1      1    13
tibble(列=模板)%>%
分离(Col,into=字典$Col_名称,
sep=头(字典$col\u end,-1),convert=TRUE)
#一个tibble:3x4
#年周性别年龄
#      
#1  2018     1      1    78
#2  2018     1      2    67
#3  2018     1      1    13
数据
dictionary太简单了不幸的是,,对不起,我应该指定一个可以扩展到数百个变量的解决方案…谢谢,但这也不能扩展到数百个变量。。。有没有一种方法可以提供起始值和结束值作为向量?你可以提供一个额外的数据集,就像你在这里展示的那样,我认为它可以用来提取起始值和结束值。好的,让我看一下,我会据此编辑我的答案。请检查更新后的解决方案是否工作得更好。这是一个有趣的练习:)
templines %>% 
  paste(collapse = "\n") %>% 
  read_fwf(., fwf_positions(start = dictionary$col_start,
                            end = dictionary$col_end,
                            col_names = dictionary$col_name))
library(tidyverse)
data.frame(Col = templines) %>% 
      separate(Col, into = dictionary$col_name, sep= head(dictionary$col_end, -1))
#  year week gender  age
#1 2018   01      1   78
#2 2018   01      2   67
#3 2018   01      1   13
tibble(Col = templines) %>% 
   separate(Col, into = dictionary$col_name, 
       sep= head(dictionary$col_end, -1), convert = TRUE)
# A tibble: 3 x 4
#   year  week gender   age
#  <int> <int>  <int> <int>
#1  2018     1      1    78
#2  2018     1      2    67
#3  2018     1      1    13
dictionary <- structure(list(col_name = c("year", "week", "gender", "age"), 
col_start = c(1L, 5L, 8L, 11L), col_end = c(4L, 6L, 8L, 13L
)), .Names = c("col_name", "col_start", "col_end"),
 class = "data.frame", row.names = c(NA, -4L))

templines <- c("201801 1  78", "201801 2  67", "201801 1  13")