簡體   English   中英

使用 r 中的粘貼嵌套 for 循環

[英]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"))))

為此,您最好將數據轉換為“長”格式,而不是當前的“寬”格式。 以下是使用dplyrtidyr示例。 我試圖評論每一行,但基本思想是為每個存儲變量度量生成一行,並且只顯示存在/不存在。 然后,您可以按區域對行進行分組,並計算“是”條目的數量。

# 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM