【问题标题】:Operations in nested loops within variables of filename format in RR中文件名格式变量内嵌套循环中的操作
【发布时间】:2020-01-16 13:49:32
【问题描述】:

以下代码在 R 中运行良好,我通过在 matlab 的嵌套循环(SID,会话)中使用“disp”函数来完成这些编码。

....
S09_06<- read.csv("09_06.csv", header=TRUE,sep=",")
S10_01<- read.csv(file="10_01.csv",header=TRUE, sep=",")
...

所以现在编码是R+matlab的结合,实际上效率不是很高。

应该有一些方法可以在 R 中实现它?

我已经根据互联网上的可能解决方案多次尝试编码如下,几乎没有修改,

SID = c(....9, 10,....)
S = 1:6

for (value in SID){
  if (value < 10)
  for (value in S){
  paste0("S0",SID,"_0",S)  = read.csv(file = paste("0",SID,"_0", S, ".csv"), header=TRUE,sep=",")
  }else{
  paste0("S",SID,"_0",S)  = read.csv(file = paste("0",SID,"_0", S, ".csv"), header=TRUE,sep=",")
  }

}

但是,下面的错误信息每次都会显示,

“文件中的错误(文件,“rt”):无效的“描述”参数”

如何进行操作?

谢谢。

【问题讨论】:

标签: r loops nested


【解决方案1】:

考虑通过首先构建文件名向量并将它们传递到lapplysapply 调用来构建数据框列表。下面使用sapply 生成命名(与未命名)数据框列表。

# CREATE VECTOR OF FILE NAMES (PASSING TWO VECTORS)
filenames <- as.vector(sapply(SID, 
                              function(x,y) paste0("S", ifelse(x < 10, 
                                                               paste0("0", x),
                                                               paste(x)), 
                                                   "_0", y),
                              S)
                      )

# CREATE NAMED LIST OF DATA FRAMES (PASSING ONE VECTOR) 
df_list <- sapply(filenames, function(i) {
                     fname <- paste0(substr(i, 2, nchar(i)),".csv")
                     read.csv(fname, header=TRUE, sep=",")
                  }, simplify=FALSE)

# ACCESS INDIVIDUAL DATA FRAMES    
df_list$S09_01  
df_list$S09_02
df_list$S09_03
...

【讨论】:

  • 谢谢@Parfait,df_list 确实是一个嵌套列表,上面提到了 SID 和 S。但是,无法读取每个 .csv 中的内容....查看 df_list 时,在 Value 列中全部变为“A data.frame with 0 rows and 1 column”。查看 df_list$SID_S 时,“表中没有可用数据”。应该有一种方法来处理嵌套循环难题并在 R 中执行一些简单的操作,例如 read.csv。让我们尝试对 R 保持一些信心:)
  • 我更新了代码,传递了 headersep 的原始参数,我认为这是多余的默认设置,但您的语言/区域设置可能有所不同。
  • 谢谢你,@Parfait。重新启动 R 后,您的代码正在运行。现在我可以继续进行进一步的步骤,例如选择必要的列、替换一些值等等,这些都是以前处理过 R+ Matlab 的:)
  • 是的,我按了几次向上图标,它显示“感谢您的反馈!声望低于 15 人的投票将被记录,但不要更改公开显示的帖子得分。”对不起,我现在只有 11 个……但我很感激你的代码让我恢复了对 R 的信心:)祝你有美好的一天
【解决方案2】:

这个问题涉及到几个问题:

  1. 如何一次读取大量csv文件,
  2. 如何从 2 个格式正确的整数输入向量创建文件名向量。

第1项之前已经被问过很多次了,也是Parfait's answer的核心。

此答案侧重于第 2 项。

作为增加的复杂性,文件名遵循"09_06.csv""10_01.csv"(包括文件扩展名)的方案,而生成的 data.frames 将命名为"S09_06""S10_01"(带有前导@987654329 @ 但没有文件扩展名)。

使用outer()sprintf() 可以简化以适当格式创建基本名称(不带前缀和文件扩展名):

SID = c(9, 10)
S = 1:6
outer(SID, S, sprintf, fmt = "%02i_%02i")
     [,1]    [,2]    [,3]    [,4]    [,5]    [,6]   
[1,] "09_01" "09_02" "09_03" "09_04" "09_05" "09_06"
[2,] "10_01" "10_02" "10_03" "10_04" "10_05" "10_06"

转换说明符 %02i 表示字段宽度为 2 个字符,输出将用前导 0s 填充。

现在,data.frames 列表可以通过 3 行代码创建:

basenames <- outer(SID, S, sprintf, fmt = "%02i_%02i")
df_list <- lapply(paste0(basenames, ".csv"), read.csv, header = TRUE, sep = ",")
names(df_list) <- paste0("S", basenames)

只是为了演示并且为了避免事先创建很多csv文件,使用print()函数代替read.csv()

basenames <- outer(SID, S, sprintf, fmt = "%02i_%02i")
df_list <- lapply(paste0(basenames, ".csv"), print) # just for demonstration
names(df_list) <- paste0("S", basenames)
df_list
$S09_01
[1] "09_01.csv"

$S10_01
[1] "10_01.csv"

$S09_02
[1] "09_02.csv"

$S10_02
[1] "10_02.csv"

$S09_03
[1] "09_03.csv"

$S10_03
[1] "10_03.csv"

$S09_04
[1] "09_04.csv"

$S10_04
[1] "10_04.csv"

$S09_05
[1] "09_05.csv"

$S10_05
[1] "10_05.csv"

$S09_06
[1] "09_06.csv"

$S10_06
[1] "10_06.csv"

创建一个 data.frame

OP 有mentioned,他想“选择必要的列,替换一些值”。这听起来好像所有文件都具有相同的结构,即相同的数量、顺序、名称和列类型。

如果所有文件都具有相同的结构,我会将它们组合在 一个 大型 data.frame 中。这比对 data.frames 列表应用所有操作更容易处理。

这就是我会用我喜欢的工具做的事情:

library(data.table)
library(magrittr)
SID = c(9, 10)
S = 1:6
filenames <-CJ(SID, S)[, sprintf("%02i_%02i.csv", SID, S)]
lapply(filenames, fread) %>% 
  set_names(filenames) %>% 
  rbindlist(idcol = "file")
         file V1 V2          V3
 1: 09_01.csv  Y 39 -0.83562861
 2: 09_01.csv  D  1  1.59528080
 3: 09_02.csv  V 74  1.51178117
 4: 09_02.csv  N  7  0.38984324
 5: 09_03.csv  O 84  0.59390132
 6: 09_03.csv  A 35  0.91897737
 7: 09_04.csv  F 40 -1.47075238
 8: 09_04.csv  Y 44 -0.47815006
 9: 09_05.csv  B 18 -0.41499456
10: 09_05.csv  M 22 -0.39428995
11: 09_06.csv  G 81 -1.16657055
12: 09_06.csv  K 13 -1.06559058
13: 10_01.csv  N 59  0.48742905
14: 10_01.csv  R 51  0.73832471
15: 10_02.csv  I 37 -0.04493361
16: 10_02.csv  Y 34 -0.01619026
17: 10_03.csv  O 28 -1.98935170
18: 10_03.csv  T 20  0.61982575
19: 10_04.csv  Z 51 -0.10278773
20: 10_04.csv  G 42  0.38767161
21: 10_05.csv  S 70  0.76317575
22: 10_05.csv  H 87 -0.16452360
23: 10_06.csv  W 84 -0.11234621
24: 10_06.csv  N 29  0.88110773
         file V1 V2          V3

请注意,第一列包含该行的来源文件名。

数据

示例文件由

创建
library(data.table)
library(magrittr)
SID = c(9, 10)
S = 1:6
fn <- outer(SID, S, sprintf, fmt = "%02i_%02i.csv")
set.seed(1L)
nr = 2L
dfl <- replicate(
  length(SID)*length(S), 
  data.frame(V1 = sample(LETTERS, nr), V2 = sample.int(100, nr), V3 = rnorm(nr)),
  simplify = FALSE
  ) %>% 
  set_names(fn) 
lapply(fn, function(x) fwrite(dfl[[x]], file = x))

【讨论】:

  • 谢谢你,@Uwe。您的解释很容易理解,并且您的 .csv 名单(SID_S)的代码得到了相同的结果。但是,在运行 'df_list
  • 这是因为我忽略了您的文件名不是"S"为前缀。我已经更正了。
  • 谢谢你,@Uwa。我们是那些总是想让编码工作的人:) 但是,我的数据格式是 UTF-16,fread 不支持。 matlab 可以毫不费力地轻松制作无尽的嵌套循环,显然在 R 中并非如此......再次感谢您注意下一步要采取的步骤。祝你有美好的一天:)
  • 哦,我明白了。 UTF-16 似乎确实是一个问题(github.com/Rdatatable/data.table/issues/2560),但根据github.com/Rdatatable/data.table/issues/2435,data.table 的开发版本 1.12.3 已经解决了这个问题,IIUC。
【解决方案3】:

谢谢你们,@Parfait @Uwe

因为 read.csv 后面有数百个步骤,而且 R 中嵌套循环的困难,促使我转向 matlab 来使这些技巧起作用。

虽然我已经得到了我想要的结果,但这就像一个半自动编码。每个与loops相关的步骤,在添加一些新的参与者时,都需要在matlab中再次修改,然后放回R中运行。

应该有一些方法来处理R中的所有代码,以减少和有效地减少R中超过10万行的代码。

在运行 ANOVA 或 Ancova 之前,需要在不同条件下单独计算每个值。还是您认为按清单处理比较好?

例如,根据不同列组合的逻辑判断,每个参与者的遗漏率或错误率?

我只能让它与R + matlab一起工作,但应该有一些方法可以单独处理R。

这就是我提出这个问题的原因,希望会有一些解决方案。

我们将不胜感激。

谢谢你,祝你有美好的一天:)

【讨论】:

  • 因为数百个嵌套循环无法在R中编码,只需要转向matlab编码来进行“真正的自动”编码,而不是“半自动”编码:)需要现在就和 R 说再见吧。但是,R 绘图仍然比其他绘图出色:)
猜你喜欢
  • 2019-02-15
  • 2012-03-29
  • 1970-01-01
  • 2015-09-15
  • 1970-01-01
  • 1970-01-01
  • 2018-07-15
  • 1970-01-01
  • 2018-06-11
相关资源
最近更新 更多