根据不同的列重塑数据
Reshaping data based on different columns
我有一个名为 'inputdata'
的数据集
Country Unknown Male Female Affected Male Female Unaffected Male Female
USA 200 120 80 130 80 50 70 40 30
AU 140 80 60 60 30 30 80 50 30
我将有两个输出数据集,如下所示,如您所见,输入数据集在这里有 3 个类别,如列名 2、5、8 中所述。
在输出数据集1中,Category列有类别,即输入数据中的列名。然后来自 country 列和 Male 列的国家将在输入中具有来自 Male 列的值。
与输出数据集 2 类似,Category 和 Country 保持不变,但第 3 列 Actuals 应具有输入中相应类别的值,即第 2、5、8 列。
这里的关键是输入数据集结构保持不变。
Output 1
Category Country Male
Unknown USA 120
Affected USA 80
Unaffected USA 40
.
.
.
Output 2
Category Country Actuals
Unknown USA 200
Affected USA 130
Unaffected USA 70
.
.
.
所以我现在所做的是,使用 for 循环使用索引对输入数据集中的每个类别进行子集化 --
例如,使用 inputdata[,c(1,i)]
和我的 'i'
变量将是 3,6,9 for output 1
和 2,5,8 for output 2
。然后创建一个数据框列表(每个类别一个)并将它们组合在一起以用于每个输出。我只是想知道是否有任何其他方法可以提高效率。
编辑:- 按要求添加我的代码,
for(i in seq(3, 9, by=3)) {
if(!exists('mylist')) mylist <- NULL
output1 <- inputdata[,c(1,i)]
if(i==3) {
output1$category <- 'unknown'
} else if (i==6) {
output1$category <- 'affected'
} else
output1$category <- 'unaffected'
mylist <- c(mylist,output1)
rm(output1)
}
for(i in seq(2, 8, by=3)) {
if(!exists('mylist')) mylist <- NULL
output2 <- inputdata[,c(1,i)]
if(i==3) {
output2$category <- 'unknown'
} else if (i==6) {
output2$category <- 'affected'
} else
output2$category <- 'unaffected'
mylist <- c(mylist,output2)
rm(output2)
}
有什么不明白的地方请告诉我。
这是一个基本的 R 方法,它使用 stack
根据特定列(即 male/female、类别)转换为 long。
#data frame of categories - You can further split of country if needed
# by split(d1, d1$country)
d1 <- data.frame(stack(df[-1][c(T, F, F)]), country = df$Country, stringsAsFactors = FALSE)
# values ind country
#1 200 Unknown USA
#2 140 Unknown AU
#3 130 Affected USA
#4 60 Affected AU
#5 70 Unaffected USA
#6 80 Unaffected AU
#create a list with two data frames (male and female)
#To split by country again, then lapply(l1, function(i) split(i, i$country))
l1 <- lapply(c('Male', 'Female'), function(i) setNames(data.frame(d1$ind,
stack(df[grepl(i, names(df))])[-2],
df$Country, stringsAsFactors = F),
c('category', i, 'country')))
#[[1]]
# category Male country
#1 Unknown 120 USA
#2 Unknown 80 AU
#3 Affected 80 USA
#4 Affected 30 AU
#5 Unaffected 40 USA
#6 Unaffected 50 AU
#[[2]]
# category Female country
#1 Unknown 80 USA
#2 Unknown 60 AU
#3 Affected 50 USA
#4 Affected 30 AU
#5 Unaffected 30 USA
#6 Unaffected 30 AU
数据
dput(df)
structure(list(Country = c("USA", "AU"), Unknown = c(200L, 140L
), Male = c(120L, 80L), Female = c(80L, 60L), Affected = c(130L,
60L), Male.1 = c(80L, 30L), Female.1 = c(50L, 30L), Unaffected = c(70L,
80L), Male.2 = c(40L, 50L), Female.2 = c(30L, 30L)), .Names = c("Country",
"Unknown", "Male", "Female", "Affected", "Male.1", "Female.1",
"Unaffected", "Male.2", "Female.2"), row.names = c(NA, -2L), class = "data.frame")
我有一个名为 'inputdata'
的数据集Country Unknown Male Female Affected Male Female Unaffected Male Female
USA 200 120 80 130 80 50 70 40 30
AU 140 80 60 60 30 30 80 50 30
我将有两个输出数据集,如下所示,如您所见,输入数据集在这里有 3 个类别,如列名 2、5、8 中所述。
在输出数据集1中,Category列有类别,即输入数据中的列名。然后来自 country 列和 Male 列的国家将在输入中具有来自 Male 列的值。
与输出数据集 2 类似,Category 和 Country 保持不变,但第 3 列 Actuals 应具有输入中相应类别的值,即第 2、5、8 列。
这里的关键是输入数据集结构保持不变。
Output 1
Category Country Male
Unknown USA 120
Affected USA 80
Unaffected USA 40
.
.
.
Output 2
Category Country Actuals
Unknown USA 200
Affected USA 130
Unaffected USA 70
.
.
.
所以我现在所做的是,使用 for 循环使用索引对输入数据集中的每个类别进行子集化 --
例如,使用 inputdata[,c(1,i)]
和我的 'i'
变量将是 3,6,9 for output 1
和 2,5,8 for output 2
。然后创建一个数据框列表(每个类别一个)并将它们组合在一起以用于每个输出。我只是想知道是否有任何其他方法可以提高效率。
编辑:- 按要求添加我的代码,
for(i in seq(3, 9, by=3)) {
if(!exists('mylist')) mylist <- NULL
output1 <- inputdata[,c(1,i)]
if(i==3) {
output1$category <- 'unknown'
} else if (i==6) {
output1$category <- 'affected'
} else
output1$category <- 'unaffected'
mylist <- c(mylist,output1)
rm(output1)
}
for(i in seq(2, 8, by=3)) {
if(!exists('mylist')) mylist <- NULL
output2 <- inputdata[,c(1,i)]
if(i==3) {
output2$category <- 'unknown'
} else if (i==6) {
output2$category <- 'affected'
} else
output2$category <- 'unaffected'
mylist <- c(mylist,output2)
rm(output2)
}
有什么不明白的地方请告诉我。
这是一个基本的 R 方法,它使用 stack
根据特定列(即 male/female、类别)转换为 long。
#data frame of categories - You can further split of country if needed
# by split(d1, d1$country)
d1 <- data.frame(stack(df[-1][c(T, F, F)]), country = df$Country, stringsAsFactors = FALSE)
# values ind country
#1 200 Unknown USA
#2 140 Unknown AU
#3 130 Affected USA
#4 60 Affected AU
#5 70 Unaffected USA
#6 80 Unaffected AU
#create a list with two data frames (male and female)
#To split by country again, then lapply(l1, function(i) split(i, i$country))
l1 <- lapply(c('Male', 'Female'), function(i) setNames(data.frame(d1$ind,
stack(df[grepl(i, names(df))])[-2],
df$Country, stringsAsFactors = F),
c('category', i, 'country')))
#[[1]]
# category Male country
#1 Unknown 120 USA
#2 Unknown 80 AU
#3 Affected 80 USA
#4 Affected 30 AU
#5 Unaffected 40 USA
#6 Unaffected 50 AU
#[[2]]
# category Female country
#1 Unknown 80 USA
#2 Unknown 60 AU
#3 Affected 50 USA
#4 Affected 30 AU
#5 Unaffected 30 USA
#6 Unaffected 30 AU
数据
dput(df)
structure(list(Country = c("USA", "AU"), Unknown = c(200L, 140L
), Male = c(120L, 80L), Female = c(80L, 60L), Affected = c(130L,
60L), Male.1 = c(80L, 30L), Female.1 = c(50L, 30L), Unaffected = c(70L,
80L), Male.2 = c(40L, 50L), Female.2 = c(30L, 30L)), .Names = c("Country",
"Unknown", "Male", "Female", "Affected", "Male.1", "Female.1",
"Unaffected", "Male.2", "Female.2"), row.names = c(NA, -2L), class = "data.frame")