我对for循环有疑问。 我有一个具有120个唯一ID的数据框。我想根据ID将数据框分为120个不同的数据框。我使用以下代码对其进行了拆分:
split_part0 <- split(PART0_DF, PART0_DF$sysid)
现在我想做
for(i in 1:120){
sys[i] <- as.data.frame(split_part0[[i]])}
这样,我有120个数据帧,它们具有唯一的帧名称,可用于进一步分析。
在这种特殊情况下无法使用“ for循环”吗?如果是这样,我还可以使用哪些其他命令?
PART0_DF
的虚拟数据:
Date sysid power temperature
1.1.2018 1 1000 14
2.1.2018 1 1200 16
3.1.2018 1 800 18
1.1.2018 2 1500 8
2.1.2018 2 800 18
3.1.2018 2 1300 11
我希望输出像
>>sys1
Date sysid power temperature
1.1.2018 1 1000 14
2.1.2018 1 1200 16
3.1.2018 1 800 18
>>sys2
1.1.2018 2 1500 8
2.1.2018 2 800 18
3.1.2018 2 1300 11
答案 0 :(得分:0)
一种简单的方法是通过将字符串sys
附加到ID号上并使用它来分割数据来创建因子向量。不需要使用for()
循环来生成所需的输出,因为当要拆分的输入是数据帧时,split()
的结果是数据帧的列表。
因子的值用于命名split()
生成的列表中的每个元素。对于OP,由于sysid
是数字,并且以1开头,所以不明显使用ID号来命名列表中的结果数据帧,如help for split()
中所述。
使用来自OP的数据,我们将说明如何使用sysid
列创建因子变量,该变量将字符串sys
与id值组合在一起,并将其拆分为数据列表可以通过名称访问的框架。
rawData <- "Date sysid power temperature
1.1.2018 1 1000 14
2.1.2018 1 1200 16
3.1.2018 1 800 18
1.1.2018 2 1500 8
2.1.2018 2 800 18
3.1.2018 2 1300 11"
data <- read.table(text = rawData,header=TRUE)
sysidName <- paste0("sys",data$sysid)
splitData <- split(data,sysidName)
splitData
...以及输出:
> splitData
$`sys1`
Date sysid power temperature
1 1.1.2018 1 1000 14
2 2.1.2018 1 1200 16
3 3.1.2018 1 800 18
$sys2
Date sysid power temperature
4 1.1.2018 2 1500 8
5 2.1.2018 2 800 18
6 3.1.2018 2 1300 11
>
这时,可以使用提取操作符的$
形式访问列表中的各个数据帧:
> splitData$sys1
Date sysid power temperature sysidName
1 1.1.2018 1 1000 14 sys1
2 2.1.2018 1 1200 16 sys1
3 3.1.2018 1 800 18 sys1
>
此外,通过使用names()
函数,可以获取数据帧列表中所有命名元素的向量。
> names(splitData)
[1] "sys1" "sys2"
>
从答案的顶部重申要点,当split()
与数据帧一起使用时,结果列表为data.frame()
类型的对象的列表。例如:
> str(splitData["sys1"])
List of 1
$ sys1:'data.frame': 3 obs. of 4 variables:
..$ Date : Factor w/ 3 levels "1.1.2018","2.1.2018",..: 1 2 3
..$ sysid : int [1:3] 1 1 1
..$ power : int [1:3] 1000 1200 800
..$ temperature: int [1:3] 14 16 18
>
for()
循环... 由于OP询问是否可以使用for()
循环解决问题,所以答案是“是”。
# create a vector containing unique values of sysid
ids <- unique(data$sysid)
# initialize output data frame list
dfList <- list()
# loop thru unique values and generate named data frames in list()
for(i in ids){
dfname <- paste0("sys",i)
dfList[[dfname]] <- data[data$sysid == i,]
}
dfList
...以及输出:
> for(i in ids){
+ dfname <- paste0("sys",i)
+ dfList[[dfname]] <- data[data$sysid == i,]
+ }
> dfList
$`sys1`
Date sysid power temperature
1 1.1.2018 1 1000 14
2 2.1.2018 1 1200 16
3 3.1.2018 1 800 18
$sys2
Date sysid power temperature
4 1.1.2018 2 1500 8
5 2.1.2018 2 800 18
6 3.1.2018 2 1300 11
在split()
,for()
和使用by()
的其他答案之间,我们如何选择最佳答案?
一种方法是确定哪个版本运行最快,因为实际数据将比原始帖子中的样本数据大得多。
我们可以使用microbenchmark
包来比较三种不同方法的性能。
split()
性能library(microbenchmark)
> microbenchmark(splitData <- split(data,sysidName),unit="us")
Unit: microseconds
expr min lq mean median uq max neval
splitData <- split(data, sysidName) 144.594 147.359 185.7987 150.1245 170.4705 615.507 100
>
for()
性能> microbenchmark(for(i in ids){
+ dfname <- paste0("sys",i)
+ dfList[[dfname]] <- data[data$sysid == i,]
+ },unit="us")
Unit: microseconds
expr min lq mean
for (i in ids) { dfname <- paste0("sys", i) dfList[[dfname]] <- data[data$sysid == i, ] } 2643.755 2857.286 3457.642
median uq max neval
3099.064 3479.311 8511.609 100
>
by()
性能> microbenchmark(df_list <- by(df, df$sysid, function(unique) unique),unit="us")
Unit: microseconds
expr min lq mean median uq max neval
df_list <- by(df, df$sysid, function(unique) unique) 256.791 260.5445 304.9296 275.9515 309.5325 1218.372 100
>
split()
,平均运行时间为186微秒,而by()
为305微秒,而for()
循环方法为3,458微秒。
答案 1 :(得分:0)
另一个选择是使用函数by()
:
df <- data.frame(
Date = c("1.1.2018", "2.1.2018", "3.1.2018", "1.1.2018", "2.1.2018", "3.1.2018"),
sysid = c(1, 1, 1, 2, 2, 2),
power = c(1000, 1200, 800, 1500, 800, 1300)
)
df
Date sysid power
1 1.1.2018 1 1000
2 2.1.2018 1 1200
3 3.1.2018 1 800
4 1.1.2018 2 1500
5 2.1.2018 2 800
6 3.1.2018 2 1300
现在使用df
并调用sysid
,将by()
分成尽可能多的数据帧,只要它们具有不同的(“唯一的”)unique
值:
df_list <- by(df, df$sysid, function(unique) unique)
df_list
df$sysid: 1
Date sysid power
1 1.1.2018 1 1000
2 2.1.2018 1 1200
3 3.1.2018 1 800
----------------------------------------------------------------------------------------------
df$sysid: 2
Date sysid power
4 1.1.2018 2 1500
5 2.1.2018 2 800
6 3.1.2018 2 1300