R for 循环或应用于数据 table 列
R for loop or apply on data table columns
正在尝试对数据框中的每一列进行一些操作。不确定使用 apply
或 for
(不确定如何忽略 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"))
})
正在尝试对数据框中的每一列进行一些操作。不确定使用 apply
或 for
(不确定如何忽略 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"))
})