R for 循环或应用于数据 table 列

R for loop or apply on data table columns

正在尝试对数据框中的每一列进行一些操作。不确定使用 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)}}

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

问题二:

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

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

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

然后保存 table: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 也可以有其他列,但它们不是必需的。

尝试这样的事情(以 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).

使用您的虚拟数据,我们可以遍历 "subject" 列 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"))
})