【问题标题】:R for loop or apply on data table columnsR for 循环或应用于数据表列
【发布时间】:2016-09-21 11:57:29
【问题描述】:

尝试对数据框中的每一列进行一些操作。不确定使用applyfor(不确定如何忽略apply 中的第一列)。

问题 1:

为了简单地把每个名字打印两次,我想出了:

for (i in names(dt)){if(str_length(i) < 3) {print(i);print(i)}}

第一列的名称是唯一一个字符串长度 > 3 这就是我使用它的原因。

我尝试使用:

for (i in dt$i){if(str_length(names(i)) < 3) {print(i);print(i)}}
for (i in dt$i){if(str_length(names(dt)) < 3) {print(i);print(i)}}

简单地打印每列两次,但它只是创建了一个空值。

问题 2:

我实际要做的不是打印两次;是每列的顺序:order(-i)??

然后创建一个子集:head(i, n=500)??

不确定这是额外步骤还是上述步骤的扩展。然后将其定义为data.frame; dt(i) &lt; data.frame(head(i, n=500))??

然后保存该表:write.csv(dt(i), "newfolder/i.csv", row.names = FALSE) - 我认为这只会不断覆盖一个名为 i.csv 的文件,不知道如何根据 i 命名该文件。

也许apply 是更好的方法,我不确定。

我最简单的方法(这样我就明白发生了什么)将不胜感激。我只有 40 列,每列有 50,000 行,所以它不应该那么慢。

编辑

为了更清楚,我将添加一个示例:

Name  Math Science PE
David  90    70    25
Tom    100   60    40
John   30    40    100

我想以 3 个 csv 结尾,第一个看起来像:

Name Math
Tom  100
David 90

在上述情况下,头部 n=2。 csv 也可以有其他列,但它们不是必需的。

【问题讨论】:

  • not sure how I'd name the file based on i. - 使用paste0("myFile", i, ".csv")
  • 您的帖子不是很清楚,可能因为过于宽泛而关闭。请添加输入数据和预期输出。 apply 只是 for loop 的美化版本,所以由你决定使用哪一个。
  • 我的编辑信息够不够?
  • 感谢您的编辑,Name 是行名还是列?
  • 它已经是一列,因此为什么在我的示例中,我在一开始就使用 str_length 作为 names(),因为这是唯一一个名称超过 2 个字母的列 - 数据表来自 csv ,我想我可以将列定义为名称,不确定这是否是更好的做法。

标签: r for-loop dataframe multiple-columns


【解决方案1】:

尝试这样的事情(以mtcars 为例):

mtcars[] <- lapply(mtcars, sort)
head(mtcars)

在这里,您将每一列从小到大排序。请注意,每个单独的行不再有用,因为它不代表特定的单位。你确实得到了你想要的输出。然后你可以使用head() 来获得你想要的条目数。

看看会发生什么:

首先,原始数据的样子:

> head(mtcars)
                   mpg cyl disp  hp drat    wt  qsec vs am gear carb
Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
Valiant           18.1   6  225 105 2.76 3.460 20.22  1  0    3    1

现在让我们对每一列进行排序:

> mtcars[] <- lapply(mtcars, sort)

输出的样子:

> head(mtcars, 5)
                   mpg cyl disp hp drat    wt  qsec vs am gear carb
Mazda RX4         10.4   4 71.1 52 2.76 1.513 14.50  0  0    3    1
Mazda RX4 Wag     10.4   4 75.7 62 2.76 1.615 14.60  0  0    3    1
Datsun 710        13.3   4 78.7 65 2.93 1.835 15.41  0  0    3    1
Hornet 4 Drive    14.3   4 79.0 66 3.00 1.935 15.50  0  0    3    1
Hornet Sportabout 14.7   4 95.1 66 3.07 2.140 15.84  0  0    3    1

您还看到,行名不再提供信息。请确保这是您想要的。要保存新数据帧的最小 500 行,只需使用常规子集,例如 df[1:500,]

为了保留名称,我们可以生成一个数据框列表:

newdat <- lapply(mtcars, function(x){
  dat <- data.frame(ind = rownames(mtcars), out = x)
  dat <- dat[order(dat$out),]
})

在这里,输出将是一个包含旧行名(称为ind)和称为out 的有序列的列表。它是一个命名列表,其中每个列表元素对应于原始列的名称。请注意,您可以进一步使用list 结构,例如lapply(newdat, head)

【讨论】:

  • 我希望在对每一列进行排序时更改行名,那么我是否会在 for 循环中使用 apply 呢?第一列是变量负载,每列代表不同的扇区。对于每个扇区,我试图对变量进行排序并保存顶部变量,这样在此之后我将编写另一个循环来绘制每个扇区。希望这是有道理的
  • @OliPaul 将行名添加为新列,然后排序。 mtcars$myNames &lt;- rownames(mtcars),然后进行排序。
  • 它们已经是,但是在循环中排序时,名称不是值,我不希望它们排序
  • 名称是一列,我只是不希望该列成为我排序和保存多个 csv 的循环的一部分
  • 然后只需将rownames(mtcars) 替换为包含名称的列的名称。同样,您需要将 mtcars 替换为数据集的名称。无论如何,如果您想保留名称,它们也需要进行排序,上面的解决方案向您展示了如何做到这一点。
【解决方案2】:

使用您的虚拟数据,我们可以遍历“主题”列 2:n,然后排序并写出前 2 个结果:

# dummy data
df <- read.table(text="Name  Math Science PE
David  90    70    25
Tom    100   60    40
John   30    40    100", header = TRUE)


# loop and write csv for top 2 scores
lapply(colnames(df)[2:ncol(df)], function(i){
  res <- df[, c("Name", i)]
  res <- res[order(res[, i], decreasing = TRUE),]
  write.csv(head(res, 2), file = paste0(i, ".csv"))
})

【讨论】:

    猜你喜欢
    • 2022-01-03
    • 2023-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-18
    • 2021-06-26
    • 2012-10-16
    • 1970-01-01
    相关资源
    最近更新 更多