【问题标题】:Beginner using pipes使用管道的初学者
【发布时间】:2021-08-26 11:37:17
【问题描述】:

我是一名初学者,我正在尝试找到最有效的方法来更改我将要创建的许多 CSV 文件的第一列的名称。创建 CSV 文件后,我将它们加载到 R 中,如下所示:

data <- read.csv('filename.csv')

我已经使用names()函数对单个文件进行了改名:

names(data)[1] <- 'Y'

但是,我想找到将此名称更改组合/管道传输到 read.csv 的最有效方法,以便在打开每个文件时将相同的名称更改应用于每个文件。我尝试编写一个“简单”函数来执行此操作:

addName <- function(data) {
  names(data)[1] <- 'Y'
  data
}

但是,我还没有完全理解编写函数的语法,我无法让它工作。

【问题讨论】:

  • 尝试使用colnames函数,见stackoverflow.com/questions/7531868/…
  • 您是否设计了您的 addName 函数,期望 R 通过引用传递?也就是说,您是否希望您的函数变异 现有对象x,在addName(x) 中作为data 参数的参数提供。如果是这样,这将不起作用:R 通过值传递 而不是通过引用。 但是data &lt;- addName(data) 行应该可以工作,data &lt;- data %&gt;% addName()magrittr 包也应该可以工作。您可以将sapply 这个addName 函数添加到data.frames 的列表中,就像您的data 对象一样,然后存储sapply 将返回的列表。

标签: r function csv columnname


【解决方案1】:

注意

如果您希望原来的 addName 函数像这样“改变”现有对象

x <- data.frame(Column_1 = c(1, 2, 3), Column_2 = c("a", "b", "c"))

# Try (unsuccessfully) to change title of "Column_1" to "Y" in x.
addName(x)

# Print x.
x

请注意,R 通过值而不是通过引用传递,因此x 本身将保持不变

  Column_1 Column_2
1        1        a
2        2        b
3        3        c

任何“突变”都可以通过用函数的返回值覆盖x来实现

x <- addName(x)

# Print x.
x

在这种情况下x 本身显然会被改变:

  Y Column_2
1 1        a
2 2        b
3 3        c

回答

无论如何,这是一个将管道(%&gt;% 来自magrittr 包)和自定义函数紧密结合的解决方案。 请注意,如果没有我为清楚起见添加的换行符和 cmets,这可能会被压缩为 只有几行代码。

# The dplyr package helps with easy renaming, and it includes the magrittr pipe.
library(dplyr)

# ...

filenames <- c("filename1.csv", "filename2.csv", "filename3.csv")

# A function to take a CSV filename and give back a renamed dataset taken from that file.
addName <- function(filename) {
  return(# Read in the named file as a data.frame.
         read.csv(file = filename) %>%
           # Take the resulting data.frame, and rename its first column as "Y";
           # quotes are optional, unless the name contains spaces: "My Column"
           # or `My Column` are needed then.
           dplyr::rename(Y = 1))
}

# Get a list of all the renamed datasets, as taken by addName() from each of the filenames.
all_files <- sapply(filenames, FUN = addName,
                    # Keep the list structure, in which each element is a
                    # data.frame.
                    simplify = FALSE,
                    # Name each list element by its filename, to help keep track.
                    USE.NAMES = TRUE)

事实上,您可以一举轻松rename 任何您想要的列:

dplyr::rename(Y = 1, 'X' = 2, "Z" = 3, "Column 4" = 4, `Column 5` = 5)

【讨论】:

  • 格雷格,非常感谢您的帮助!您首先描述的关于不改变 X 的函数的内容正是发生的情况。也感谢您详细而清晰的评论,对于像我这样的初学者来说,这非常有帮助。你介意澄清一下,每次我打开 17 个文件中的一个时,我是否必须运行 addName 函数和“sapply()”,以及“sapply()”在做什么以及如何做?一般来说,我在理解如何链接和组织产生预期结果所需的不同步骤时遇到问题。
  • 嗨@Dodo! sapply 所做的就是这个。假设您有一个函数接受 single 值 (my_fun &lt;- function(x) {return(2*x)}) 并返回(比如说)该值的双精度值。假设您还有一个包含 多个 值的向量 (my_vals &lt;- c(1, 2, 3)) 或列表 (my_vals &lt;- list(1, 2, 3))。你可以很容易地通过my_fun(1) 得到2my_fun(2) 得到4my_fun(3) 得到6。但是说你想要所有这些结果,一气呵成!然后sapply(my_vals, FUN = my_fun)my_fun 应用于my_values 中的每个值,以获得结果的向量(或列表):2 4 6
  • 因此,在我的回答中,您 (@Dodo) 所需要的只是您正在处理的所有 filenames 的向量(或列表)。您有一个 addName 函数,旨在接受任何 one 文件名并返回从该文件中获取的重命名数据集(data.frame)。现在您需要做的就是将filenamesaddName 提供给一个single sapply 语句,该语句循环遍历all filenames,调用addName在每一个上,并将结果(重命名的数据集)放入一个公共列表中(与文件名的顺序相同)。我们将这个列表(data.frames 的列表)保存在变量 all_files 中。
【解决方案2】:

这将读取一个文件名向量,将每个文件的第一列的名称更改为“Y”并将所有文件存储在一个列表中。

filenames <- c("filename1.csv","filename2.csv")
addName <- function(filename) {
  data <- read.csv(filename)
  names(data)[1] <- 'Y'
  data
}
files <- list()
for (i in 1:length(filenames)) {
   files[[i]] <- addName(filenames[i])
}

【讨论】:

  • 你不能用简单的files &lt;- sapply(X = filenames, FUN = addName) 替换addName 定义之后的所有内容吗?
  • 当然可以,它可能也更快。但是我是这样写的,因为 OP 提到他们是初学者,作为初学者,我发现这样的代码更容易理解。
  • 感谢您对 Baroque 的回答,但我发现以我有限的初学者技能很难遵循和理解代码。我了解函数部分,但是我以前没有经验的 for 循环超出了我的想象。我知道循环是为了循环文件而编写的,但我根本不懂语法。是否有一个很好的初学者学习资源可以推荐用于循环?另外,循环是函数的一部分还是单独的?
  • 嗨@Dodo!函数定义以右大括号 addName &lt;- function(filename) { ... } 结尾;所以addName() 将接受filename 参数,并返回从该文件加载的重命名数据集(data.frame)。之后的一切都在函数之外。接下来files &lt;- list() 创建一个列表,该列表最初为空,但将由循环填充。 for 循环遍历每个文件名,从 1st 到 2nd:在每一步,它都会添加当前 (ith) 数据集(由 addName() 从当前 i 获得th 文件名)作为新的 (ith) 元素添加到列表中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多