R:按行拆分连接的数据帧
我有一个大的文本文件,它是另一个程序将多个表附加在一起(包括标题)的结果。我想把那个文件读入R并分开 这有点类似于,只是我不知道行号,我需要在标题行上拆分它,而不是特定的行号。不过,我知道每个表都以一个标题开头,而且Wvlgth值始终以337.0开头,以823.0结尾 这是文本文件。它看起来与此相同,只是有550行R:按行拆分连接的数据帧,r,R,我有一个大的文本文件,它是另一个程序将多个表附加在一起(包括标题)的结果。我想把那个文件读入R并分开 这有点类似于,只是我不知道行号,我需要在标题行上拆分它,而不是特定的行号。不过,我知道每个表都以一个标题开头,而且Wvlgth值始终以337.0开头,以823.0结尾 这是文本文件。它看起来与此相同,只是有550行 Wvlgth Global 337.0 .4345 337.5 .1256 338.0 .8754 <...> 821.0 .9923 822.0 .7124
Wvlgth Global
337.0 .4345
337.5 .1256
338.0 .8754
<...>
821.0 .9923
822.0 .7124
823.0 .2999
Wvlgth Global
337.0 .5632
337.5 .1245
338.0 .0012
<...>
821.0 .1987
822.0 .6743
823.0 .2045
我希望将其转换为多个数据帧,如下所示:
数据帧1
Wvlgth全局
1 337.0 .4345
2 337.5 .1256
3 338.0 .8754
548 821.0 .9923
549 822.0 .7124
550 823.0 .2999
数据帧2
Wvlgth全局
1 337.0 .5632
2 337.5 .1245
3 338.0 .0012
548 821.0 .1987
549 822.0 .6743
550 823.0 .2045
不确定是否有办法通过read.csv实现这一点,或者我是否需要读取整个内容并在事后将其拆分。以下是如何使用
从数据表拆分来实现这一点。基本上,您需要在第1列的“Wvlgth”上使用cumsum
创建一个组列。然后可以将结果拆分为一个列表。然后可以像这样访问该列表的元素:df_list[[1]]
df <- read.table(text="Wvlgth Global
337.0 .4345
337.5 .1256
338.0 .8754
821.0 .9923
822.0 .7124
823.0 .2999
Wvlgth Global
337.0 .5632
337.5 .1245
338.0 .0012
821.0 .1987
822.0 .6743
823.0 .2045",header=FALSE,stringsAsFactors=FALSE)
df$group <- cumsum(df[,1]=="Wvlgth")
df_list <- split(df, list(df$group))
$`1`
V1 V2 group
1 Wvlgth Global 1
2 337.0 .4345 1
3 337.5 .1256 1
4 338.0 .8754 1
5 821.0 .9923 1
6 822.0 .7124 1
7 823.0 .2999 1
$`2`
V1 V2 group
8 Wvlgth Global 2
9 337.0 .5632 2
10 337.5 .1245 2
11 338.0 .0012 2
12 821.0 .1987 2
13 822.0 .6743 2
14 823.0 .2045 2
此外,如果要设置data.frames的列名,可以使用lappy
:
new_col_name <- c("Wvlgth", "Global","group")
df_list <- lapply(df_list, setNames, nm = new_col_name) #set names
df_list <- lapply(df_list, function(x) x[-1,]) #remove first row
> df_list
$`1`
Wvlgth Global group
2 337.0 .4345 1
3 337.5 .1256 1
4 338.0 .8754 1
5 821.0 .9923 1
6 822.0 .7124 1
7 823.0 .2999 1
$`2`
Wvlgth Global group
9 337.0 .5632 2
10 337.5 .1245 2
11 338.0 .0012 2
12 821.0 .1987 2
13 822.0 .6743 2
14 823.0 .2045 2
new\u col\u name我自己创建了一些蒙特卡罗
为了将其转换为更有用的格式(data.table):
然后我们申请
l1<-split(dt,cumsum(dt$containsNA))
最后,为了获得我们想要的格式(删除NA行和containsNA
列),我们对列表的每个元素执行以下操作:
lapply(l1,function(x) x[,.SD[(!is.na(Wvlgth))]][,containsNA:=NULL])
导致:
$`1`
Wvlgth Global
1: 337.0 0.4345
2: 337.5 0.1256
3: 338.0 0.8754
4: 821.0 0.9923
5: 822.0 0.7124
6: 823.0 0.2999
$`2`
Wvlgth Global
1: 327.0 0.53450
2: 317.5 0.52560
3: 358.0 0.47540
4: 871.0 0.93235
5: 882.0 0.21240
6: 893.0 0.19990
7: 811.0 0.93235
8: 972.0 0.33235
$`3`
Wvlgth Global
1: 893 0.2399
2: 193 0.5120
3: 892 0.3199
增编:
如果指向MC数据的链接被弃用,下面是用于特定问题的data
Wvlgth Global
337.0 0.4345
337.5 0.1256
338.0 0.8754
821.0 0.9923
822.0 0.7124
823.0 0.2999
Wvlgth Global
327.0 0.5345
317.5 0.5256
358.0 0.4754
871.0 0.93235
882.0 0.2124
893.0 0.1999
811.0 0.93235
972.0 0.33235
Wvlgth Global
893.0 0.2399
193.0 0.5120
892.0 0.3199
我没见过在进口上做这件事的方法。您可以使用readLines
或系统工具修复文件(在R中),也可以通过使用df[!grepl('\\D',df$Wvlgnth),]
子集并手动应用type.convert
来手动修复data.frame。我将作为.numeric
导入,然后使用NA
将其拆分,NA
作为rows@agerom我想我不明白你在说什么,对不起……使用NA行作为分割数据帧的标志与使用一行字符串有什么不同?@ale19你介意共享csv的一部分吗?@agerom是我原始帖子中的一部分吗?这还不够?行!非常感谢。如果要求不多,为什么需要将结果拆分为一个列表?当我在没有list()
的情况下运行那行代码时,我遇到了一个错误,但我不明白这个错误是什么意思,即使在谷歌搜索了一下。@ale19如果你在split(df,list(df$group))
中引用list
,这只是数据的方式。table
使用输入。更广泛地说,在这种情况下,最好将data.frames存储到列表中。如您所见,使用Lappy对所有data.frames进行操作很容易。如果需要将结果返回到单个data.frame中,可以使用data.table.Ah中的rbindlist,这很有意义!在熊猫中,连接数据帧也是一样的,但我没有意识到这一点。还在学习R中的所有语法。谢谢!
#loading libraries
library(stringi)
library(data.table)
library(plyr)
input <- readLines("path/to/your/csv",warn = F)#reading input csv file
input <- trimws(input)#removing spaces left and right
>input
[1] "Wvlgth Global" "337.0 0.4345" "337.5 0.1256" "338.0 0.8754" "821.0 0.9923" "822.0 0.7124" "823.0 0.2999" "Wvlgth Global" "327.0 0.5345" "317.5 0.5256"
[11] "358.0 0.4754" "871.0 0.93235" "882.0 0.2124" "893.0 0.1999" "811.0 0.93235" "972.0 0.33235" "Wvlgth Global" "893.0 0.2399" "193.0 0.5120" "892.0 0.3199"
dt<-data.table(ldply(stri_split(str = input,fixed=" "),"["))#creating data.table
dt[,Wvlgth:=as.numeric(V1)][,Global:=as.numeric(V2)][,V1:=NULL][,V2:=NULL]#performing some column manipulation (by importing as.numeric, the characters are transformed into NA's
dt[,containsNA:=is.na(Wvlgth)]#adding boolean tag if Wvlgth is NA
>dt
Wvlgth Global containsNA
1: NA NA TRUE
2: 337.0 0.43450 FALSE
3: 337.5 0.12560 FALSE
4: 338.0 0.87540 FALSE
5: 821.0 0.99230 FALSE
6: 822.0 0.71240 FALSE
7: 823.0 0.29990 FALSE
8: NA NA TRUE
9: 327.0 0.53450 FALSE
10: 317.5 0.52560 FALSE
11: 358.0 0.47540 FALSE
12: 871.0 0.93235 FALSE
13: 882.0 0.21240 FALSE
14: 893.0 0.19990 FALSE
15: 811.0 0.93235 FALSE
16: 972.0 0.33235 FALSE
17: NA NA TRUE
18: 893.0 0.23990 FALSE
19: 193.0 0.51200 FALSE
20: 892.0 0.31990 FALSE
l1<-split(dt,cumsum(dt$containsNA))
>l1
$`1`
Wvlgth Global containsNA
1 NA NA TRUE
2 337.0 0.4345 FALSE
3 337.5 0.1256 FALSE
4 338.0 0.8754 FALSE
5 821.0 0.9923 FALSE
6 822.0 0.7124 FALSE
7 823.0 0.2999 FALSE
$`2`
Wvlgth Global containsNA
8 NA NA TRUE
9 327.0 0.53450 FALSE
10 317.5 0.52560 FALSE
11 358.0 0.47540 FALSE
12 871.0 0.93235 FALSE
13 882.0 0.21240 FALSE
14 893.0 0.19990 FALSE
15 811.0 0.93235 FALSE
16 972.0 0.33235 FALSE
$`3`
Wvlgth Global containsNA
17 NA NA TRUE
18 893 0.2399 FALSE
19 193 0.5120 FALSE
20 892 0.3199 FALSE
lapply(l1,function(x) x[,.SD[(!is.na(Wvlgth))]][,containsNA:=NULL])
$`1`
Wvlgth Global
1: 337.0 0.4345
2: 337.5 0.1256
3: 338.0 0.8754
4: 821.0 0.9923
5: 822.0 0.7124
6: 823.0 0.2999
$`2`
Wvlgth Global
1: 327.0 0.53450
2: 317.5 0.52560
3: 358.0 0.47540
4: 871.0 0.93235
5: 882.0 0.21240
6: 893.0 0.19990
7: 811.0 0.93235
8: 972.0 0.33235
$`3`
Wvlgth Global
1: 893 0.2399
2: 193 0.5120
3: 892 0.3199
Wvlgth Global
337.0 0.4345
337.5 0.1256
338.0 0.8754
821.0 0.9923
822.0 0.7124
823.0 0.2999
Wvlgth Global
327.0 0.5345
317.5 0.5256
358.0 0.4754
871.0 0.93235
882.0 0.2124
893.0 0.1999
811.0 0.93235
972.0 0.33235
Wvlgth Global
893.0 0.2399
193.0 0.5120
892.0 0.3199