Mon ensemble de données comprend les scores et le nombre total de répondants pour les questions posées dans une enquête, sur plusieurs exercices (FY13, FY14 & FY15) et dans différentes régions.
Mon objectif est de parcourir le FY
et identifiez le moment où chaque question a été posée, pour chaque région. Et stockez ces informations dans une nouvelle colonne.
Voici à quoi ressemble un échantillon reproductible -
for (i in unique(testdf$ID)) { v=unique(testdf$FY) if(('FY15' %in% v) & ('FY14' %in% v)) { testdf$Tally=='Asked Over The Past Two Years' } else if(('FY15' %in% v) & ('FY14' %in% v) & ('FY13' %in% v)) { testdf$Tally=='Asked Over The Past Three Years' } else if(('FY13' %in% v) & ('FY15' %in% v)) { testdf$Tally=='Question Asked in FY13 & FY15 Only' } else { testdf$Tally=='Question Asked Once Only' } }
Je commence par créer une colonne d'ID, en concaténant Région
& QST
library(tidyr) testdf = testdf %>% unite(ID,c('Region','QST'),sep = "",remove = F)
Mon objectif
1) Pour chaque ID
unique, identifiez si la question donnée a été posée -
a) Uniquement sur un an (soit FY13, FY14 ou FY15)
b) Au cours des deux dernières années (FY15 & FY14 uniquement)
c) Au cours des trois dernières années (FY15 & FY14 & FY13)
d) Uniquement pour les FY13 & FY15
Ma tentative
Pour ce problème, j'ai essayé de créer une boucle for
, et pour chaque ID
unique , Je stocke d'abord les occurrences uniques de chaque FY où la question a été posée dans un vecteur v
. Ensuite, en utilisant une instruction conditionnelle IF, j'attribue un commentaire à une colonne nouvellement créée appelée Tally
en fonction de ces occurrences.
testdf=data.frame(FY=c("FY13","FY14","FY15","FY14","FY15","FY13","FY14","FY15","FY13","FY15","FY13","FY14","FY15","FY13","FY14","FY15"), Region=c(rep("AFRICA",5),rep("ASIA",5),rep("AMERICA",6)), QST=c(rep("Q2",3),rep("Q5",2),rep("Q2",3),rep("Q5",2),rep("Q2",3),rep("Q5",3)), Very.Satisfied=runif(16,min = 0, max=1), Total.Very.Satisfied=floor(runif(16,min=10,max=120)), Satisfied=runif(16,min = 0, max=1), Total.Satisfied=floor(runif(16,min=10,max=120)), Dissatisfied=runif(16,min = 0, max=1), Total.Dissatisfied=floor(runif(16,min=10,max=120)), Very.Dissatisfied=runif(16,min = 0, max=1), Total.Very.Dissatisfied=floor(runif(16,min=10,max=120)))
La boucle semble fonctionner sans lançant un message d'erreur, mais cela ne semble pas créer la nouvelle colonne Tally
.
Toute aide à ce sujet sera grandement appréciée.
4 Réponses :
Dans votre code, le problème principal est que dans la clause if-else vous ne faites pas une affectation (en utilisant ' XXX
Sortie:
+------------------------------------------------------------+ | ID FY13 FY14 FY15 tally | +------------------------------------------------------------+ | 1 AFRICAQ2 1 1 1 Asked Over The Past Three Years | | 2 AFRICAQ5 0 1 1 Asked Over the Past Two Years | | 3 AMERICAQ2 1 1 1 Asked Over The Past Three Years | | 4 AMERICAQ5 1 1 1 Asked Over The Past Three Years | | 5 ASIAQ2 1 1 1 Asked Over The Past Three Years | | 6 ASIAQ5 1 0 1 Asked in FY12 & FY15 Only | +------------------------------------------------------------+
Vous devriez peut-être poster votre sortie.
Pas besoin de boucle:
result %>% mutate(Tally = case_when(FY13 + FY14 + FY15 == 1 ~ "Only one year", FY13 + FY14 + FY15 == 3 ~ "Past three years", FY14 + FY15 == 2 ~ "Past two years", FY13 + FY15 == 2 ~ "FY13 and FY15 only", NA ~ NA_character_)) QST Region FY13 FY14 FY15 Tally 1 Q2 AFRICA 1 1 1 Past three years 2 Q2 AMERICA 1 1 1 Past three years 3 Q2 ASIA 1 1 1 Past three years 4 Q5 AFRICA NA 1 1 Past two years 5 Q5 AMERICA 1 1 1 Past three years 6 Q5 ASIA 1 NA 1 FY13 and FY15 only
Répond aux quatre questions en une seule fois.
Si vous vraiment voulez une colonne de pointage, développez-la comme ceci:
library(tidyverse) result <- testdf %>% select(3, 2, 1) %>% mutate(Asked = 1) %>% spread(FY, Asked) > result QST Region FY13 FY14 FY15 1 Q2 AFRICA 1 1 1 2 Q2 AMERICA 1 1 1 3 Q2 ASIA 1 1 1 4 Q5 AFRICA NA 1 1 5 Q5 AMERICA 1 1 1 6 Q5 ASIA 1 NA 1
Pensez à ave
pour regrouper le calcul par Région et QST à l'intérieur de ifelse
imbriqués pour la logique conditionnelle:
testdf <- within(testdf, { FY13 <- ifelse(FY=='FY13', 1, 0) FY14 <- ifelse(FY=='FY14', 1, 0) FY15 <- ifelse(FY=='FY15', 1, 0) Tally <- ifelse(ave(FY13, Region, QST, FUN=max) + ave(FY14, Region, QST, FUN=max) + ave(FY15, Region, QST, FUN=max) == 1, 'Asked Only on One Year', ifelse(ave(FY13, Region, QST, FUN=max) + ave(FY14, Region, QST, FUN=max) + ave(FY15, Region, QST, FUN=max) == 3, 'Asked Over the Past Three Years', ifelse(ave(FY14, Region, QST, FUN=max) + ave(FY15, Region, QST, FUN=max) == 2, 'Asked Over the Past Two Years', ifelse(ave(FY13, Region, QST, FUN=max) + ave(FY15, Region, QST, FUN=max) == 2, 'Asked On FY13 & FY15 Only', NA ) ) ) ) FY13 <- NULL; FY14 <- NULL; FY15 <- NULL }) testdf[c("ID", "FY", "Tally")] # Region QST FY Tally # 1 AFRICA Q2 FY13 Asked Over the Past Three Years # 2 AFRICA Q2 FY14 Asked Over the Past Three Years # 3 AFRICA Q2 FY15 Asked Over the Past Three Years # 4 AFRICA Q5 FY14 Asked Over the Past Two Years # 5 AFRICA Q5 FY15 Asked Over the Past Two Years # 6 ASIA Q2 FY13 Asked Over the Past Three Years # 7 ASIA Q2 FY14 Asked Over the Past Three Years # 8 ASIA Q2 FY15 Asked Over the Past Three Years # 9 ASIA Q5 FY13 Asked On FY13 & FY15 Only # 10 ASIA Q5 FY15 Asked On FY13 & FY15 Only # 11 AMERICA Q2 FY13 Asked Over the Past Three Years # 12 AMERICA Q2 FY14 Asked Over the Past Three Years # 13 AMERICA Q2 FY15 Asked Over the Past Three Years # 14 AMERICA Q5 FY13 Asked Over the Past Three Years # 15 AMERICA Q5 FY14 Asked Over the Past Three Years # 16 AMERICA Q5 FY15 Asked Over the Past Three Years
Il existe une solution utilisant votre colonne ID. (En utilisant Nous Maintenant, nous savons déjà si la question a été posée au cours des différentes années. Pour répondre aux autres questions, nous ferons quelques calculs. Les séquences dans les colonnes 5: 7 contiennent les informations traduire en langage humain par niveaux de facteurs, et fusionner avec le bloc de données d'origine pour atteindre résultat souhaité. paste0
, nous pouvons le faire un peu mieux, mais avec testdf $ ID .)
dcast
votre testdf
en utilisant le package reshape2
. testdf <- structure(list(FY = c("FY13", "FY14", "FY15", "FY14", "FY15",
"FY13", "FY14", "FY15", "FY13", "FY15", "FY13", "FY14", "FY15",
"FY13", "FY14", "FY15", "FY15"), Region = c("AFRICA", "AFRICA",
"AFRICA", "AFRICA", "AFRICA", "ASIA", "ASIA", "ASIA", "ASIA",
"ASIA", "AMERICA", "AMERICA", "AMERICA", "AMERICA", "AMERICA",
"AMERICA", "ANTH.CTRY"), QST = c("Q2", "Q2", "Q2", "Q5", "Q5",
"Q2", "Q2", "Q2", "Q5", "Q5", "Q2", "Q2", "Q2", "Q5", "Q5", "Q5",
"Q2")), row.names = c(NA, 17L), class = "data.frame")
> merge(testdf, t3[c(1, 8)])
ID FY Region QST Tally
1 AFRICA_Q2 FY13 AFRICA Q2 Asked Over The Past Three Years
2 AFRICA_Q2 FY14 AFRICA Q2 Asked Over The Past Three Years
3 AFRICA_Q2 FY15 AFRICA Q2 Asked Over The Past Three Years
4 AFRICA_Q5 FY14 AFRICA Q5 Asked Over The Past Two Years
5 AFRICA_Q5 FY15 AFRICA Q5 Asked Over The Past Two Years
6 AMERICA_Q2 FY13 AMERICA Q2 Asked Over The Past Three Years
7 AMERICA_Q2 FY14 AMERICA Q2 Asked Over The Past Three Years
8 AMERICA_Q2 FY15 AMERICA Q2 Asked Over The Past Three Years
9 AMERICA_Q5 FY13 AMERICA Q5 Asked Over The Past Three Years
10 AMERICA_Q5 FY14 AMERICA Q5 Asked Over The Past Three Years
11 AMERICA_Q5 FY15 AMERICA Q5 Asked Over The Past Three Years
12 ANTH.CTRY_Q2 FY15 ANTH.CTRY Q2 Question Asked Once Only
13 ASIA_Q2 FY13 ASIA Q2 Asked Over The Past Three Years
14 ASIA_Q2 FY14 ASIA Q2 Asked Over The Past Three Years
15 ASIA_Q2 FY15 ASIA Q2 Asked Over The Past Three Years
16 ASIA_Q5 FY13 ASIA Q5 Question Asked in FY13 & FY15 Only
17 ASIA_Q5 FY15 ASIA Q5 Question Asked in FY13 & FY15 Only
Tally
souhaitées que nous peut traire tmp$Tally <- factor(tmp$Tally, labels=c('Question Asked Once Only',
'Question Asked in FY13 & FY15 Only',
'Asked Over The Past Three Years',
'Asked Over The Past Two Years'))
tmp$Tally <- apply(tmp, 1, function(x) paste0(x[5:7], collapse=""))
Résultat
tmp <- cbind(tmp,
past2=as.numeric(t2[3] + t2[4] == 2 & t2[2] == 0),
past3=as.numeric(t2[2] + t2[3] + t2[4] == 3),
y13_15=as.numeric(t2[2] + t2[4] == 2 & t2[3] == 0))
Données
library(reshape2)
tmp <- dcast(testdf, ID ~ FY,
value.var="QST", fun.aggregate=length)