[英]Nested for loop using paste in r
我有一個包含多個是/否列的數據集,指示特定記錄是否與三個不同區域中的給定商店編號相關聯(即,對於三個不同區域中的兩個商店之一,記錄將具有單個是值區域,其中變量名稱的格式為 'region'_'storenumber'):
var1_1 var1_2 var2_1 var2_2 var3_1 var3_2
1 Yes No No Yes Yes No
2 No Yes Yes No No Yes
3 No Yes Yes No No Yes
4 No Yes No Yes Yes No
5 No Yes No Yes No Yes
6 Yes No No Yes No Yes
7 Yes No Yes No Yes No
8 No Yes Yes No No Yes
我想為每個區域創建一個名為“region_1”、“region_2”和“region_3”的變量,它們等於該區域中該記錄的“是”商店編號(1 或 2):
region_1 region_2 region_3
1 1 2 1
2 2 1 2
3 2 1 2
4 2 2 1
5 2 2 2
6 1 2 2
7 1 1 1
8 2 1 2
我能夠使用 for 循環分別創建每個區域變量,如下所示:
for(i in 1:3) {
df[paste("region_", toString(i), sep = "")] <- ""
}
for(i in 1:2) {
df$region_1 <- ifelse(df[paste("var1_", toString(i), sep = "")] == "Yes" & df$region_1 == "", toString(i), df$region_1)
}
for(i in 1:2) {
df_1$region_2 <- ifelse(df_1[paste("var2_", toString(i), sep = "")] == "Yes" & df_1$region_2 == "", toString(i), df_1$region_2)
}
for(i in 1:2) {
df_1$region_3 <- ifelse(df_1[paste("var3_", toString(i), sep = "")] == "Yes" & df_1$region_3 == "", toString(i), df_1$region_3)
}
我的實際數據有 3 個以上的區域(每個區域有 2 個以上的商店),因此我不想為每個區域編寫單獨的循環,而是想嵌套這個循環來循環所有區域。 我嘗試了以下操作:
for(j in 1:3) {
for(i in 1:2) {
df[paste("region_", toString(j), sep = "")] <- ifelse(df[paste("var", toString(j), "_", toString(i), sep = "")] == "Yes" & df[paste("region_", toString(j), sep = "")] == "", toString(i), df[paste("region_", toString(j), sep = "")])
}
}
但收到警告“提供了#### 變量來替換 1 個變量”,最終每個區域變量填充了每個記錄的相同單個值。
關於我的嵌套循環哪里出錯的任何想法?
如果我們將 Yes 和 No 轉換為邏輯值,我們可以簡單地做
regions = as.data.frame( sapply(seq(1, NCOL(stores), by=2),function(j) ifelse(stores[,j],1,2)))
names(regions) = c("region_1", "region_2", "region_3")
regions
# region_1 region_2 region_3
#1 1 2 1
#2 2 1 2
#3 2 1 2
#4 2 2 1
#5 2 2 2
#6 1 2 2
#7 1 1 1
#8 2 1 2
數據:
library(data.table)
stores = setDF(fread(gsub("No", "FALSE", gsub("Yes", "TRUE",
"var1_1 var1_2 var2_1 var2_2 var3_1 var3_2
Yes No No Yes Yes No
No Yes Yes No No Yes
No Yes Yes No No Yes
No Yes No Yes Yes No
No Yes No Yes No Yes
Yes No No Yes No Yes
Yes No Yes No Yes No
No Yes Yes No No Yes"))))
為此,您最好將數據轉換為“長”格式,而不是當前的“寬”格式。 以下是使用dplyr
和tidyr
示例。 我試圖評論每一行,但基本思想是為每個存儲變量度量生成一行,並且只顯示存在/不存在。 然后,您可以按區域對行進行分組,並計算“是”條目的數量。
# Data entry from @dww, without conversion to logical (though that would make it easier)
library(data.table)
stores = setDF(fread("var1_1 var1_2 var2_1 var2_2 var3_1 var3_2
Yes No No Yes Yes No
No Yes Yes No No Yes
No Yes Yes No No Yes
No Yes No Yes Yes No
No Yes No Yes No Yes
Yes No No Yes No Yes
Yes No Yes No Yes No
No Yes Yes No No Yes"))
更改為長格式,存儲為新變量
longStores <-
stores %>%
# tag for printing
tbl_df() %>%
# Store the variable of interest as a column, instead of row.names
mutate(variableInterest = rownames(.)) %>%
# Convert the data to long format
gather(StoreID, present, -variableInterest) %>%
# Split the store_region format
separate(StoreID, c("Store", "Region"), sep = "_") %>%
# Eliminate the leading "var" from store names, just for display
mutate(Store = gsub("var", "", Store))
按地區匯總,仍為長格式
longRegional <-
longStores %>%
# Set grouping
group_by(variableInterest, Region) %>%
# Count the number of correct values in the region
summarise(nStoresWithVariable = sum(present == "Yes"))
最后,重新格式化為您的原始請求
longRegional %>%
spread(Region, nStoresWithVariable)
# variableInterest `1` `2`
# * <chr> <int> <int>
# 1 1 2 1
# 2 2 1 2
# 3 3 1 2
# 4 4 1 2
# 5 5 0 3
# 6 6 1 2
# 7 7 3 0
# 8 8 1 2
這是我將您的數據模擬為 True 和 False 的混亂嘗試:
模擬數據 - 使用隨機布爾值生成數據表
rb <- function()
{
sample(c(T,F), size=10, replace=TRUE, prob=c(0.5, 0.5) )
}
var1_1 = rb()
var2_1 = rb()
var3_1 = rb()
df <- data.frame( var1_1, !var1_1,
var2_1, !var2_1,
var3_1, !var3_1)
colnames(df) = c('var1_1', 'var1_2', 'var2_1', 'var2_2', 'var3_1', 'var3_2')
df
var1_1 var1_2 var2_1 var2_2 var3_1 var3_2
1 FALSE TRUE TRUE FALSE FALSE TRUE
2 FALSE TRUE FALSE TRUE FALSE TRUE
3 FALSE TRUE TRUE FALSE TRUE FALSE
4 FALSE TRUE TRUE FALSE FALSE TRUE
5 FALSE TRUE FALSE TRUE TRUE FALSE
6 FALSE TRUE FALSE TRUE TRUE FALSE
7 TRUE FALSE TRUE FALSE TRUE FALSE
8 TRUE FALSE FALSE TRUE TRUE FALSE
9 TRUE FALSE FALSE TRUE TRUE FALSE
10 FALSE TRUE FALSE TRUE TRUE FALSE
解決方案
cn <- names(df)
cnprefixes <- gsub("_.*?$","",cn)
cnsuffixes <- gsub("^.*?_","",cn)
newblock<-data.frame()
bFirstTime<-T
for (prefix in unique(cnprefixes))
{
block<-df[ , grepl( prefix , names( df ) ) ]
theseSuffixes <- cnsuffixes[startsWith(cn, prefix)]
j <- 1
for(suffix in theseSuffixes)
{
block[,j][block[,j]==T]=as.numeric(suffix)
j<-j+1
}
tempblock=data.frame(rowSums(block))
colnames(tempblock)<- prefix
if (bFirstTime){
newblock <- tempblock
bFirstTime <- F
}
else{
newblock<-cbind(newblock, tempblock)
}
}
新區塊
var1 var2 var3
1 2 1 2
2 2 2 2
3 2 1 1
4 2 1 2
5 2 2 1
6 2 2 1
7 1 1 1
8 1 2 1
9 1 2 1
10 2 2 1
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.