2017-05-18 3 views
0

J'essaie de trouver la valeur moyenne par type d'élément, puis définissez une variable y qui prend la valeur:Essayer de regrouper par moyenne et puis couper les valeurs aberrantes des observations basées sur la moyenne dans KDB

  1. valeur manquante si x = 0,
  2. y = x. Ensuite les valeurs rondes qui sont trop grands ou trop petits:
  3. si x> 0, x> mu, définissez alors y = mu
  4. si x < 0, x < mu, puis réglez y = mu

C'est ce que je l'ai essayé, qui ne produit pas le résultat désiré ci-dessous:

tab2:([]items:`a`b`a`a`b; x:-6 8 0 -3 5) 
tabsum: select mu:avg x by items from tab2; 
tab2: update y:x from tab2 
tab2: update y:mu from tab2 where x > 0 and x > mu/get error after running above step 
tab2: update y:mu from tab2 where x < 0 and x <= mu 

résultat souhaité:

items x mu y 
    a -6 -3.0 -3.0 
    b 8 6.5 6.5 
    a 0 -3.0 NaN 
    a -3 -3.0 -3.0 
    b 5 6.5 5 

Relatif à ces données:

i) NaN est-il le type approprié pour les valeurs manquantes dans kdb? (NA est différent de NaN ou NULL dans R par exemple). Je suppose que c'est basé sur ce que j'ai lu jusqu'ici. Ii) Existe-t-il un code plus efficace pour obtenir la colonne mu à l'intérieur de tab2? Faire une autre table et je suppose que la fusion n'est pas efficace (bases encore l'apprentissage de la KDB)

iii) Si je viens de lancer

tab2:([]items:`a`b`a`a`b; x:-6 8 0 -3 5) 
    tabsum: select mu:avg x by items from tab2; 
    tab2: update y:mu from tab2 where x > 0 and x > mu 

Je reçois:

items x mu y 
1  a -6 -3.0 NaN 
2  b 8 6.5 6.5 
3  a 0 -3.0 NaN 
4  a -3 -3.0 NaN 
5  b 5 6.5 6.5 

Ligne 5 n'a pas de sens pour moi. Pourquoi y = 6.5 si x < mu? Je m'attends à y = 5 pour cette rangée. Clairement, ma compréhension de ce qui se passe est fausse.

iv) Comment puis-je obtenir le résultat souhaité (le code que j'ai posté ne fonctionne pas correctement)

Répondre

3

Cela pourrait ne pas être la solution la plus jolie, mais semble correspondre à vos critères. J'utilise un vecteur conditionnel ? pour définir la valeur de y:

q)show tab3: update y:?[((x>0) and x>mu) or ((x<0) and x<=mu);mu;x] from update mu:avg x by items from tab2 
items x mu y 
---------------- 
a  -6 -3 -3 
b  8 6.5 6.5 
a  0 -3 0 
a  -3 -3 -3 
b  5 6.5 5 

Et puis en remplaçant toutes les valeurs y=0 avec null0n (plutôt que NaN):

q)update y:0n from tab3 where y=0 
items x mu y 
---------------- 
a  -6 -3 -3 
b  8 6.5 6.5 
a  0 -3  
a  -3 -3 -3 
b  5 6.5 5 

Le résultat inattendu sur votre dernière la ligne est en ordre d'exécution; q Le code est exécuté de droite à gauche. Alors:

5>0 and 5>6.5 

signifie réellement:

5>(0 and 5>6.5) 

qui est:

5>0 

qui évalue à true.Pour effectuer la comparaison souhaitée, vous devez utiliser des parenthèses:

q)(5>0) and 5>6.5 
0b 

Il existe plusieurs raisons pour lesquelles votre bloc de code ne fonctionne pas. Sur la ligne 2, vous ne mettez pas à jour tab2 avec la colonne mu; vous venez de créer une nouvelle table. Par conséquent, lorsque vous essayez d'utiliser mu sur la ligne 4, il n'existe pas (ce qui provoquera une erreur). Sur la ligne 3, vous définissez les valeurs de y comme étant égales à x, mais cela signifie également le même type (entier). Ensuite, lorsque vous essayez de réinitialiser y à une valeur flottante à partir de mu, vous obtenez une erreur 'type.

est ici un bloc de code semblable à la vôtre qui fonctionne:

q)tab2:([]items:`a`b`a`a`b; x:-6 8 0 -3 5) 
q)tab2: update mu:avg x by items from tab2 
q)tab2: update y:"f"$x from tab2 
q)tab2: update y:mu from tab2 where (x>0) and (x> mu) 
q)tab2: update y:mu from tab2 where (x<0) and (x<= mu) 
q)tab2 
items x mu y 
---------------- 
a  -6 -3 -3 
b  8 6.5 6.5 
a  0 -3 0 
a  -3 -3 -3 
b  5 6.5 5 
+0

merci pour le lien et l'explication! logique –

1

Vous pouvez faire cela en une ligne:

tab3: update y:?[abs[x]>abs[mu];mu;x] from (update mu:avg x by items from tab2) where x<>0