Thursday, January 26, 2017

Carré Racine De Une Matrice In Stata Forex

Bienvenue à l'Institut de recherche et d'éducation numériques Stata FAQ Comment accéder aux informations stockées après avoir exécuté une commande dans Stata (résultats renvoyés) En plus de la sortie de la fenêtre de résultats, plusieurs commandes Statas stockent des informations sur la commande Et ses résultats en mémoire. Cela permet à l'utilisateur, ainsi qu'aux autres commandes Stata, de faire facilement usage de cette information. Stata appelle ces résultats retournés. Les résultats retournés peuvent être très utiles lorsque vous souhaitez utiliser les informations produites par une commande Stata pour faire autre chose dans Stata. Par exemple, si vous voulez dire centre une variable, vous pouvez utiliser résumer pour calculer la moyenne, puis utiliser la valeur de la moyenne calculée par synthèse pour centrer la variable. L'utilisation des résultats retournés éliminera la nécessité de retaper ou de couper et coller la valeur de la moyenne. Un autre exemple de la façon dont les résultats retournés peut être utile est si vous voulez générer des valeurs prédites de la variable de résultat lorsque les variables de prédiction sont à un ensemble spécifique de valeurs, ici encore, vous pourriez retaper les coefficients ou utiliser couper et coller, mais les résultats retournés Rendre la tâche beaucoup plus facile. La meilleure façon d'obtenir une idée de la façon dont les résultats retournés travail est de sauter à droite dans et commencer à regarder et à les utiliser. Le code ci-dessous ouvre un exemple de jeu de données et utilise un résumé (somme abrégée) pour générer des statistiques descriptives pour la variable lue. Cela produit la sortie attendue, mais plus important encore pour nos besoins, Stata a maintenant des résultats de la commande de résumé stockée dans la mémoire. Mais comment pouvez-vous savoir quelles informations ont été stockées Une liste des informations enregistrées par chaque commande est inclus dans le fichier d'aide andor manuel imprimé, donc je pourrais y regarder, mais je peux aussi taper la liste de retour. Qui affichera tous les résultats retournés en mémoire. Ci-dessus est une liste des résultats retournés, comme vous pouvez le voir chaque résultat est de la forme r (.) Où les ellipses (quot. Quot) est une étiquette courte. Nous pouvions voir le fichier d'aide de la commande summary pour savoir ce que chaque élément de la liste est, mais il est souvent facile de déterminer quelle valeur est attribuée à ce résultat, par exemple, r (moyenne). Pas surprenant contient la moyenne de lecture (vous pouvez vérifier cela contre la sortie), mais d'autres ne sont pas aussi évident, par exemple r (sumw). Pour ceux-ci, vous devrez peut-être consulter le manuel si vous pensez que vous pourriez vouloir les utiliser. La plupart du temps, le processus sera relativement facile parce que vous saurez quel résultat vous voulez accéder, vous allez regarder la liste pour savoir à quel nom il est stocké sous, plutôt que de regarder la liste et d'essayer de comprendre ce que chaque L'article est. Comme vous pouvez l'imaginer, les différentes commandes, et même la même commande avec des options différentes, enregistrent des résultats différents. Ci-dessous nous résumons la variable lue à nouveau, mais ajoutez l'option detail. Ensuite, nous utilisons la liste de retour pour obtenir la liste des résultats retournés. De même que l'option de détail ajoute des informations supplémentaires à la sortie, il en résulte également des informations supplémentaires stockées dans les résultats retournés. La nouvelle liste comprend tous les renseignements renvoyés par la commande de somme ci-dessus, plus la kurtose d'asymétrie et un certain nombre de percentiles, y compris les quartiles de 1ère (r (p25)) et 3ème (r (p75)) et la médiane (r (p50) ). Maintenant que nous avons un certain sens de ce que les résultats sont retournés par la commande de résumé, nous pouvons faire usage des résultats retournés. En suivant l'un des exemples cités ci-dessus, nous entendons le centre de la variable read. En supposant que la dernière commande que nous avons exécutée était la commande de résumé ci-dessus, le code ci-dessous utilise génère une nouvelle variable, cread qui contient les valeurs moyennes centrées de read. Notez qu'au lieu d'utiliser la valeur réelle de la moyenne de la lecture dans cette commande, nous avons utilisé le nom du résultat retourné (ie r (moyenne)), Stata sait quand il voit r (moyenne) que nous entendons la valeur stockée dans Cette variable système. Sur la ligne suivante, nous résumons la nouvelle variable cread. Alors que la moyenne n'est pas exactement égale à zéro, elle est dans l'erreur d'arrondissement de zéro, donc nous savons que nous avons bien centré la variable lire. Comme le code ci-dessus suggère, nous pouvons utiliser les résultats retournés à peu près de la même manière que nous utiliserions un nombre réel. C'est parce que Stata utilise le r (.) Comme un espace réservé pour une valeur réelle. Pour un autre exemple de ceci, disons que nous voulons calculer la variance de la lecture de son écart-type (en ignorant le fait de résumer renvoie la variance dans r (Var)). Nous pouvons le faire à la volée en utilisant la commande d'affichage comme calculatrice. La deuxième ligne de code ci-dessous fait cela. Nous pouvons même vérifier le résultat en coupant et en collant la valeur de l'écart-type de la sortie, ce qui est fait dans la troisième commande ci-dessous. Les résultats sont fondamentalement les mêmes, la très légère différence est l'erreur d'arrondi car l'estimation stockée r (sd) contient plus de chiffres de précision que la valeur de l'écart type affiché dans la sortie. Types de résultats renvoyés, r-classe et e-classe Maintenant que vous connaissez un peu les résultats retournés et comment ils fonctionnent vous êtes prêt pour un peu plus d'informations sur eux. Les résultats renvoyés se présentent en deux types principaux: r-class et e-class (il existe également des variables de classe s et c-class, mais nous ne les discuterons pas ici). Les commandes qui effectuent l'estimation, par exemple les régressions de tous les types, l'analyse factorielle et l'anova sont des commandes de classe e. D'autres commandes, par exemple les commandes de synthèse, de corrélation et de post-estimation, sont des commandes de classe r. La distinction entre les commandes r-class et e-class est importante car Stata stocke les résultats des commandes e-class et r-class dans différents quotplaces. quot Cela a deux ramifications pour vous en tant qu'utilisateur. Tout d'abord, vous devez savoir si les résultats sont stockés dans r () ou e () (ainsi que le nom du résultat) afin de pouvoir les utiliser. Si vous n'êtes pas sûr de la classe dans laquelle vous exécutez une commande, vous pouvez soit la rechercher dans le fichier d'aide, soit quotlookquot en un seul endroit (en utilisant la commande appropriée pour lister les résultats), si les résultats ne sont pas stockés là, L'autre. Une ramification potentiellement plus importante de la différence dans la façon dont les résultats des commandes r-class et e-class sont retournées est que les résultats renvoyés sont conservés en mémoire uniquement jusqu'à ce qu'une autre commande de la même classe soit exécutée. Autrement dit, les résultats renvoyés par les commandes précédentes sont remplacés par des commandes ultérieures de la même classe. En revanche, l'exécution d'une commande d'une autre classe n'affectera pas les résultats renvoyés. Par exemple, si je fais une régression, puis une seconde régression, les résultats de la première régression (stockée dans e ()) sont remplacés par ceux de la seconde régression (également stockés dans e ()). Cependant, si au lieu d'une seconde régression, j'ai exécuté une commande post-estimation, les résultats de la régression resteraient dans e () alors que les résultats de l'instruction post-estimation seraient placés dans r (). Bien qu'il y ait une distinction entre les deux, l'utilisation réelle des résultats des commandes r-class et e-class est très similaire. Pour commencer, les commandes sont parallèles, pour énumérer les résultats de la classe r stockés dans la mémoire, la commande est la liste de retour. Pour faire la même chose pour les résultats d'e-class la commande ereturn liste. En outre, à l'exception de la différence dans les conventions d'appellation (r () contre e ()), les résultats sont accédés de la même manière. L'exemple ci-dessous démontre ceci, d'abord nous régressons écrire sur femelle et lire. Puis utilisez ereturn liste pour regarder les résultats retournés. La liste des résultats renvoyés pour la régression comprend plusieurs types de résultats renvoyés répertoriés sous les rubriques scalaires, macros, matrices et fonctions. Nous allons discuter des types de résultats retournés ci-dessous, mais pour l'instant nous montrerons comment vous pouvez utiliser les résultats scalaires retournés de la même manière que nous avons utilisé les résultats retournés de résumer. Par exemple, une façon de calculer la variance des erreurs après une régression est de diviser la somme résiduelle de carrés par les degrés de liberté totaux (c'est-à-dire n-1). La somme résiduelle des carrés est stockée dans e (rss) et que le n pour l'analyse est mémorisé dans e (N). Ci-dessous nous utilisons la commande d'affichage comme une calculatrice, avec les résultats retournés pour calculer la variance des erreurs. Comment les résultats sont renvoyés: Scalaires, chaînes, matrices et fonctions Comme mentionné ci-dessus, pour les commandes r-class et e-class, il existe plusieurs types de résultats renvoyés, y compris les scalaires, les chaînes, les matrices et les fonctions. Dans les listes de résultats renvoyés, chaque type est répertorié sous sa propre rubrique. Les résultats énumérés sous le titre quotscalarsquot sont juste cela, une valeur numérique unique. Leur utilisation est discutée ci-dessus, alors nous ne dirons plus à leur sujet dans cette section. Les résultats renvoyés répertoriés sous quotmacrosquot sont généralement des chaînes qui fournissent des informations sur la commande exécutée. Par exemple, dans les résultats renvoyés pour la régression illustrée ci-dessus, e (cmdline) contient la commande que l'utilisateur a émise (sans abréviations). Ceux-ci sont généralement utilisés dans la programmation Stata. Les résultats énumérés dans les quotmatrices sont, comme on peut s'y attendre, des matrices. Alors que la liste des résultats renvoyés par la liste de retour et la liste erturn vous montre les valeurs prises par la plupart des résultats retournés, ce n'est pas pratique avec les matrices, mais les dimensions des matrices sont répertoriées. Pour afficher le contenu des matrices, vous devez les afficher à l'aide de commandes matricielles. Nous le faisons ci-dessous avec la matrice des coefficients (e (b)) en utilisant la liste de matrices de commande e (b). (Notez qu'il existe une autre façon d'accéder aux coefficients et à leurs erreurs-types après avoir adapté un modèle, ceci est discuté ci-dessous.) Si nous voulons effectuer des opérations matricielles sur des matrices retournées ou souhaiter accéder à des éléments individuels de la matrice, Déplacer la matrice stockée comme résultat renvoyé vers une matrice Stata normale. Ceci se fait dans la dernière ligne de syntaxe ci-dessous. Enfin, les résultats renvoyés sous le titre quotfunctionsquot contiennent des fonctions qui peuvent être utilisées d'une manière similaire à d'autres fonctions Stata. La fonction la plus courante renvoyée par les commandes d'estimation Stata est probablement e (échantillon). Cette fonction marque l'échantillon utilisé lors de l'estimation de la dernière analyse, ce qui est utile car les jeux de données contiennent souvent des valeurs manquantes, ce qui entraîne que tous les cas de l'ensemble de données utilisé dans une analyse donnée ne sont pas tous utilisés. En supposant que la dernière exécution de l'instruction d'estimation était la régression de l'écriture sur la femelle et la lecture ci-dessus, la première ligne de code ci-dessous utilise e (échantillon) pour trouver la moyenne de lecture parmi les cas utilisés dans le modèle. La deuxième ligne de code utilise e (échantillon) pour créer une nouvelle variable appelée flag qui est égale à 1 pour les cas qui ont été utilisés dans l'analyse, et zéro autrement. (Notez que l'exemple de jeu de données ne contient aucune donnée manquante, tous les cas sont inclus dans l'analyse, et le drapeau est une constante égale à un.) Coefficients et leurs erreurs standard Comme discuté ci-dessus, après un modèle, les coefficients et leur norme Les erreurs sont stockées dans e () sous forme matricielle. Ces matrices permettent à l'utilisateur d'accéder aux coefficients, mais Stata vous donne un moyen encore plus simple d'accéder à cette information en la stockant dans les variables système b et se. Pour accéder à la valeur d'un coefficient de régression après une régression, il suffit de taper bvarname où varname est le nom de la variable prédictive dont vous voulez examiner le coefficient. Pour accéder à l'erreur standard, vous pouvez simplement taper sevarname. Pour accéder au coefficient et à l'erreur-type de la constante, nous utilisons bcons et secons respectivement. Ci-dessous, nous exécutons le même modèle de régression que nous avons exécuté au-dessus (en omettant la sortie), en utilisant female et read to predict write. Une fois que nous avons estimé le modèle, nous utilisons l'instruction display pour montrer que les valeurs de b sont égales à nos coefficients de régression. Enfin, nous calculons la valeur prédite de l'écriture lorsqu'un élève de sexe féminin (femelle 1) a un score de lecture de 52. Le contenu de ce site Web ne doit pas être interprété comme un endossement d'un site Web, d'un livre ou d'un logiciel Université de Californie. Introduction à Mata Mata est un langage matriciel construit dans Stata, semblable à bien des égards à R, Matlab ou GAUSS. Il a quelques caractéristiques uniques et intrigantes cependant. La première est qu'il s'agit d'une langue compilée plutôt que d'une interprétation, ce qui améliore la performance. Il a également été parallélisé dans StataMP (disponible sur tous les serveurs Linux de SSCC et Condor) qui améliore considérablement les performances. D'autre part Mata est assez nouveau et n'a pas encore quotcaught onquot à la SSCC, donc nous n'avons pas de comparaisons du monde réel à offrir. Mata n'est pas un remplaçant de Stata, ni un paquet statistique autonome. C'est un outil qui est mieux utilisé comme un complément à Stata (ou SAS ou SPSS), pour faire ces choses Stata ne fait pas bien sur ses propres. En particulier, Mata ne fonctionne pas dans le contexte d'un ensemble de données unique, ce qui lui donne une flexibilité supplémentaire. Mais vous ne devriez pas essayer d'apprendre Mata sauf si vous êtes déjà familier avec Stata ou un autre paquet statistique. Mata est un langage relativement bas. Une grande partie de votre temps dans Stata (ou SAS ou SPSS) est dépensé en utilisant des programmes intégrés, trouver juste la bonne combinaison d'options pour obtenir Stata de faire ce que vous voulez. Dans Mata vous allez prendre le contrôle direct, en disant à Mata ce que vous voulez faire étape par étape. (L'optimiseur Mata, dont nous allons discuter longuement, est une exception notable.) Cela signifie que faire des choses simples est généralement plus lourde dans Mata que dans Stata, mais Mata a moins de contraintes. Cet article est principalement écrit pour les personnes qui ont une expérience significative en utilisant la syntaxe Stata, SAS ou SPSS, mais pas d'autres langages de programmation. Ainsi, l'accent sera mis sur l'apprentissage des objets utiles en manipulant les matrices, et de nombreux exemples sont conçus pour donner de l'expérience ainsi que pour illustrer un concept particulier. Les anciens combattants de Matlab et GAUSS peuvent trouver qu'ils peuvent parcourir ces sections, en se concentrant sur ce qui est nouveau pour eux. Les programmeurs de C trouveront que Mata imite C chaque fois qu'il peut, ainsi ils peuvent probablement écrémer les sections sur des constructions de programmation standard comme des boucles. Mais peu importe ce que votre arrière-plan, vous apprendrez beaucoup plus si vous lisez cet article à l'ordinateur, avec Stata en cours d'exécution, et effectivement taper dans les exemples. Mata s'exécute dans Stata, donc afin d'utiliser Mata youll besoin de savoir comment exécuter un programme Stata, appelé un fichier do. Si vous n'avez jamais utilisé Stata, s'il vous plaît lire la section sur les fichiers do dans An Introduction to Stata. Interactive Stata (c'est-à-dire le démarrage et le type de commandes) est un excellent moyen d'apprendre et thats comment youll faire les exemples dans cet article. Mais pour le vrai travail vous voulez écrire tout dans les fichiers. Il existe plusieurs exemples de fichiers associés à cet article. Il ya des liens vers eux dans le texte comme ils sont utilisés. Toutefois, si vous utilisez un serveur SSCC Linux, vous pouvez les copier tous à l'avance. Pour ce faire, tapez ce qui suit à l'invite Linux: mkdir mataclass cd mataclass cp usrglobalwebssccpubsfiles4-26. La plupart des commandes de type que vous lisez sont également contenues dans mataclass. do. Les deux exemples principaux se trouvent dans ex1.do et ex2.do. Mata Basics Pour démarrer Mata, démarrez tout d'abord Stata, puis tapez dans la fenêtre de commande. Stata passera alors au mode quotMata. Il est facile d'oublier quel mode vous êtes, mais si vous regardez attentivement au bas de la fenêtre d'examen, où vous voyez normalement une période youll voyez maintenant un deux-points. Bien sûr, lorsque vous commencez Mata theres une grande ligne horizontale qui dit mata mais qui ne sera pas visible pour longtemps. Cette barre vous rappelle également une autre commande utile: pour sortir du mode Mata, tapez While Stata est organisé autour de commandes, Mata est organisé autour de quotstatements. quot Par exemple, vous pouvez simplement taper et Mata retournera stocker les résultats dans une variable est Tout aussi facile: Notez qu'il n'y avait pas de sortie cette fois. Si vous voulez voir la valeur de x, tapez simplement: et vous obtiendrez 4 en arrière. Opérateurs matriciels Dans nos exemples précédents, le signe plus a agi en tant qu'opérateur: Mata l'a reconnu en disant quottake la chose avant le signe plus et la chose après le signe plus et les additionne. Mata définit également des opérateurs matriciels qui effectuent des manipulations matricielles. Colonne et ligne jointe La virgule est définie comme l'opérateur quotcolumn joinquot, ou quottake les choses avant et après la virgule et les mettre côte à côte. Ce moyen est interprété par Stata comme une matrice avec une ligne et deux colonnes. En fait, tapez-le et la sortie sera: La barre oblique inverse (non. Ce qui est la division) est l'opérateur de quotrow joinquot, ou quottake la chose avant la barre oblique inverse et l'empiler sur le dessus de la chose après it. quot est donc une matrice avec Deux rangées et une colonne: Les choses à exploiter ne sont pas limitées aux scalaires, donc vous pouvez construire des matrices. Messages d'erreur Il existe des limites: ltistmtgt: erreur de conformabilité 3200 r (3200) Vous ne pouvez pas créer une matrice dont la première ligne a deux colonnes mais dont la deuxième et la troisième lignes ont une colonne. Stata appelle cela une erreur de conformabilité, une classe qui comprend également des choses comme essayer de multiplier les matrices où le nombre de colonnes de la première matrice est différent du nombre de lignes de la seconde. C'est aussi une erreur quotruntimequot. Lorsque vous donnez à Mata une instruction, la première chose qu'il fait est de compiler l'instruction en code octet. À ce moment, Mata ne regarde pas les quantités spécifiques à manipuler. Tout ce qu'il voit est quotput quelque chose à côté de quelque chose d'autre, puis empiler que sur le dessus de deux autres things. quot Cela fait sens, donc l'énoncé compile avec succès. Ce n'est que lorsque le code s'exécute Mata remarque que les choses à empiler ont un nombre de colonnes différentes. Une erreur de temps de compilation est générée lorsque l'instruction n'a pas de sens, peu importe les quantités que vous branchez en elle. Par exemple, l'expression incorrecte r (3000) Les erreurs de temps de compilation sont toujours le code d'erreur 3000 et ne comprennent pas ltistmtgt. Noter si une erreur est une erreur de temps de compilation ou une erreur d'exécution peut vous aider à trouver le problème. Si c'était le temps d'exécution, vous savez que Mata a au moins compris votre code (bien qu'il n'y ait aucune garantie qu'il a compris que cela signifiait la même chose que vous comprenez cela signifie) et c'était quelque chose sur les quantités spécifiques avec lesquelles il a travaillé qui a causé le problème. Si son temps de compilation, le code ne fait même pas de sens pour Mata. Parenthèses Lorsque vous assemblez des matrices, vous pouvez inclure des parenthèses pour clarifier les choses. Sa plupart pour votre bénéfice: sont tous les mêmes à Mata, mais si l'un d'eux semble plus clair pour vous par tous les moyens d'utiliser ce style dans tous vos programmes. (Je suis un fan de la troisième.) Opérateurs de plage Un autre ensemble d'outils pratiques pour créer des matrices sont les opérateurs de plage. Le. L'opérateur crée une série commençant à partir du numéro à gauche jusqu'au nombre à droite et les rend en un vecteur ligne. Le. Opérateur fait la même chose mais les place dans un vecteur colonne. Ce n'est pas limité aux nombres entiers, cependant: Notez que le nombre sur la droite n'est pas garanti pour faire partie de la série résultante. Les résultats des instructions matricielles peuvent évidemment être enregistrés dans des variables comme les autres énoncés. Par exemple: Notez comment la définition de z ressemble beaucoup à l'instruction que nous avons essayé plus tôt qui a donné une erreur d'exécution. Il s'exécute maintenant parce que x et y ont deux colonnes. C'est pourquoi il a été une erreur d'exécution et non pas une erreur de temps de compilation: étant donné les bonnes entrées, l'instruction peut fonctionner. Opérateurs arithmétiques Les opérateurs arithmétiques standard reconnaissent quand un ou les deux de leurs arguments est une matrice et agissent en conséquence. Cela comprend l'addition et la soustraction, la matrice des temps scalaires et la multiplication matricielle complète. Cependant, il existe aussi des opérateurs quotcolonquot qui travaillent élément par élément. Pour l'addition et la soustraction il ne fait aucune différence, puisque theyre élément par élément de toute façon. Mais il fait beaucoup de différence avec la multiplication. Considérons ce qui suit: Opérateurs logiques Les opérateurs logiques tels que supérieur, inférieur et égal à sont également définis dans les deux versions de matrice et de côlon (notez que l'opérateur égal est, par opposition à l'affectation). Toutefois, Mata n'a pas de type de variable booléenne. Ainsi (comme dans Stata) les opérateurs logiques renvoient un pour vrai et zéro pour faux. Si vous comparez deux matrices en utilisant une norme supérieure, inférieure ou égale, Mata renvoie une si et seulement si la condition est vraie pour tous les éléments des deux matrices. Sinon, il renvoie zéro Ces opérateurs ne peuvent travailler que sur des matrices de même taille. Dans leur forme colon, le résultat est une matrice contenant toutes les comparaisons élément par élément. La forme du côlon permet plus de flexibilité sur les tailles des matrices à comparer. Si un argument est un vecteur scalaire, un vecteur ligne ou un vecteur colonne, il sera dupliqué au besoin pour correspondre à l'autre matrice. L'opérateur de transposition est la citation simple droite (). Il fonctionne sur un seul objet, celui à sa gauche, et retourne sa transposition: Il n'y a pas d'opérateur inverse, cependant. L'inversion est réalisée par des fonctions. Subscriptions Pour référencer un élément particulier d'une matrice, placez le nombre de lignes et de colonnes entre crochets après le nom de la matrice. Étant donné la matrice x définie ci-dessus, x1,1 est 1. x1,2 est 2. Les sous-caractères peuvent être utilisés de chaque côté d'un signe égal: Si une matrice est un vecteur ligne ou colonne, vous pouvez utiliser un seul indice. QuotMissingquot pour le numéro de ligne ou de colonne est considéré comme signifiant toutes les lignes ou colonnes. Vous pouvez utiliser soit la période standard pour manquer, soit laisser simplement le numéro. Ainsi vous pouvez également remplacer n'importe quel nombre par un vecteur ligne ou colonne (et Stata ne se soucie pas celui que vous utilisez). Cependant, cette fois les parenthèses sont nécessaires pour que Mata sache où la liste des lignes se termine et les colonnes commencent. Vous pouvez répéter des lignes ou des colonnes, mélanger l'ordre, ou même créer des matrices plus grand que l'original. Les vecteurs prédéfinis sont également très bien: Notez que l'utilisation d'indices vectoriels comme celui-ci sera plus rapide que la multiplication par une matrice de permutation. Mata se réfère aux indices que nous avons utilisés jusqu'à présent comme quotlistquot subscripts. Chaque élément que nous voulions était énuméré explicitement (bien, sauf pour le sens manquant quotallquot). Mais vous voudrez souvent spécifier une gamme de lignes et de colonnes. Theres pas beaucoup besoin de gammes avec de petites matrices, donc commencez par créer une plus grande matrice: Prenez un moment pour essayer de comprendre comment cela a fonctionné avant de lire plus loin. La première ligne définit x1 comme un vecteur de ligne en utilisant l'opérateur de plage. La seconde définit un vecteur de colonne x2, en utilisant à nouveau l'opérateur de plage, mais en multipliant le résultat par dix. Le troisième définit alors x comme dix copies de x1 empilées les unes sur les autres plus dix copies de x2 placées l'une à côté de l'autre. Le résultat est une matrice de dix par dix qui va de 11 à 110, ce qui facilitera la lecture des lignes et colonnes que nous avons extraites dans les exemples suivants. Une méthode d'extraction d'une gamme de lignes et de colonnes à partir de x est d'utiliser les opérateurs de plage dans les indices de la liste. Ainsi, pour obtenir les lignes 3-7 et les colonnes 4-8, vous pourriez faire: Ceci est exactement équivalent à la saisie: les indices de la plage vraie, cependant, sont différents. D'une part, ils sont contenus entre crochets et le caractère de la pipe (shift-backslash). Il ya deux éléments, séparés par une barre oblique inverse: la ligne et la colonne du coin supérieur gauche de la plage désirée et le coin inférieur droit de la plage désirée. Ainsi, l'équivalent de Pensez-y comme remplaçant quotrows quatre à sept et les colonnes trois à huit quot avec quote everything entre la rangée quatre, la colonne trois et la ligne sept, la colonne huit, inclusive. quot manquant peut signifier plusieurs choses dans les indices de gamme. Si elle est utilisée pour spécifier le coin supérieur gauche, cela signifie soit la première ligne soit la première colonne. S'il est utilisé pour spécifier le coin inférieur droit, cela signifie soit la dernière ligne soit la dernière colonne. C'est tout simplement tout x. Il n'y a pas non plus de règle qui indique que les coins supérieurs gauche et inférieur droit ne peuvent pas être sur la même rangée ou colonne. Cela signifie quotrow trois, de la troisième colonne à la fin. Obtenir vos données de Stata à Mata La plupart du temps, vous ne serez pas la création de matrices à la main. Au lieu de cela vous voulez faire des matrices contenant les données que vous avez déjà dans Stata. Vous êtes également susceptible de vouloir prendre vos résultats de Mata et de les copier à votre jeu de données Stata. La première question à laquelle vous devez répondre est de savoir si vous voulez faire une nouvelle copie de vos données ou si vous voulez que Mata fonctionne directement avec les données Stata. Mata peut définir des matrices qui sont en fait quotviewsquot de vos données Stata. Pensez à une vue en donnant juste à vos données Stata un nom que Mata peut utiliser. Les vues utilisent une quantité insignifiante de mémoire même si vos données sont très volumineuses. Si vous modifiez les tables d'une matrice de vue, les données Stata sont également modifiées. Si vous faites une copie des données à la place, vous pouvez apporter des modifications et garder l'original intact, mais vous utiliserez deux fois plus de mémoire. Pour faire des copies de vos données, vous utiliserez la famille de fonctions stdata. Le plus simple et le plus rapide est stdata. Il est utilisé pour obtenir un seul numéro de votre jeu de données. Il faut deux arguments: un numéro d'observation et un nombre variable. Pensez à votre ensemble de données comme une matrice déjà, et le nombre de la variable est simplement le numéro de la colonne de la variable que vous voulez. Pour voir cela en action, finissez Mata en tapant end. Charger l'ensemble de données d'exemple automobile, énumérer une observation, et retourner dans Mata: fin sysuse auto l dans 1 mata Maintenant, obtenez le prix de la première voiture en tapant: Le résultat sera 4099, ce qui correspond à ce que vous venez de mentionner. Essayez d'autres variables pour vous assurer que vous avez l'idée. Notez que si vous essayez d'obtenir la première colonne vous obtiendrez une valeur manquante. C'est parce que stdata est uniquement pour les données numériques. Pour les chaînes, utilisez stsdata qui fonctionne à peu près de la même manière. Mata peut rechercher les nombres de colonne pour vous en utilisant la fonction stvarindex. Il prend le nom de la variable que vous voulez et retourne l'index. Cependant, ce processus ralentira légèrement les choses. Notez que vous pouvez utiliser la sortie d'une fonction comme argument pour une autre fonction: Si vous voulez plus d'une valeur, utilisez stdata. Stdata peut être utilisé comme stdata (bien que dans ce cas stdata est plus rapide). Cependant, stdata est plus flexible sur les arguments qu'il acceptera. Le numéro de ligne peut être manquant, auquel cas toutes les observations sont retournées. Il peut également s'agir d'un vecteur colonne, auquel cas seules les observations spécifiées sont renvoyées. Il peut également s'agir d'une matrice à deux colonnes. Chaque rangée représente alors une plage d'observations. Une absence dans ce cas est interprétée comme la dernière observation. Le numéro de colonne peut également être manquant (toutes les variables) ou un vecteur répertoriant les variables souhaitées. Il peut également accepter les noms des variables plutôt que leur nombre, mais ce sera plus lent. Il ne vous permet pas de spécifier des plages comme vous le pouvez pour les lignes. Comme stdata. Stdata ne peut pas gérer les chaînes. Mais il existe un stsdata équivalent. Essayez ceci: stdata (.) Stdata ((1,3), 2) stdata (1, (2,4)) stdata (1, (quotpricequot, quotrep78quot)) stsdata (., 1) Naturellement, tous ces résultats pourraient être Stockés dans des matrices pour une utilisation future. Stdata peut également prendre un troisième argument: une variable de sélection. Il peut s'agir de l'index ou du nom d'une variable, et si elle est spécifiée, seules les observations où cette variable n'est pas égale à zéro sont renvoyées. Choisir 0 comme variable de sélection a une signification particulière: dans ce cas, les observations seront exclues si elles ont une valeur manquante pour n'importe quelle variable spécifiée. Stview crée des vues sur vos données plutôt que de les copier, mais vous pouvez sélectionner des lignes et des variables en utilisant exactement les mêmes méthodes que stdata. Toutefois, stview vous donne les résultats d'une manière différente. Avec stdata. La matrice que vous vouliez était ce que la fonction stdata retournait. Vous pouvez ensuite stocker les résultats ou simplement les laisser s'afficher à l'écran. Avec stview. La fonction elle-même ne renvoie rien. Au lieu de cela, vous devez passer dans une matrice qui sera remplacée par la vue que vous sélectionnez. Une prise est que la matrice doit exister avant que vous le passiez dedans. Il n'importe pas comment grand il est - en fait il sera complètement remplacé - mais si vous essayez de passer une matrice à stview qui n'a pas été défini d'une certaine manière vous obtiendrez Une erreur d'exécution. Un moyen facile est de simplement définir la matrice que vous souhaitez utiliser à zéro avant de le transmettre po Vous pouvez même faire cela à l'intérieur de votre appel de fonction: x et n ressemblent maintenant à une matrice régulière, mais gardez à l'esprit qu'ils sont en fait des vues . Si votre objectif dans l'utilisation d'une vue est d'économiser de la mémoire, vous devez faire attention de ne pas en faire des copies. Ne crée pas une nouvelle vue. Il crée une nouvelle matrice contenant les valeurs de x une copie. Plus subtilement, crée une copie de la jième colonne de x. Si vous avez besoin d'une colonne particulière de x, vous pouvez simplement créer une nouvelle vue: Theres aucune limite au nombre de vues différentes que vous pouvez configurer pour les mêmes données. Obtenir vos données de Mata à Stata Si tout ce que vous voulez faire est de changer les valeurs des variables existantes, de faire une vue et de changer à volonté. Mais si vous voulez ajouter de nouvelles variables vous aurez besoin d'un couple de fonctions supplémentaires. Staddvar ajoute une nouvelle variable. Il prend deux arguments: le type de variable et le nom de variable. Il retourne l'index de la variable, bien que le stockage que pour une utilisation future est facultatif. Permet de créer une nouvelle variable: weightmpg (donc, pound-miles par gallon, une unité que seul un ingénieur pourrait aimer). Notez que la matrice appelée mpg est maintenant une vue de toutes les lignes de la variable mpg. Pour explorer cette nouvelle variable à l'aide des outils Stata que vous connaissez, tapez end. (Pour quitter cette nouvelle variable à l'aide des outils Stata dont vous êtes familiarisé, tapez end.) (Pour quotpmq). Bien sûr, il s'agit d'un remplacement extraordinairement maladroit pour le gen longtemps. Cela conduit à un principe général: utiliser Mata pour ce que son bon, et Stata pour ce que son bon. Il existe une grande variété d'autres fonctions que vous pouvez utiliser pour communiquer entre Mata et Stata, y compris l'ajout d'observations et l'obtention ou le réglage de macros locales, de vecteurs e () et r () et bien plus encore. Consultez le manuel pour plus de détails. Sauvegarde et chargement des données Mata Le plus souvent, le but d'un programme Mata est de prendre vos données Stata, de trouver un résultat, puis de les afficher ou de les remettre dans vos données Stata. Cependant, vous pouvez enregistrer les matrices Mata si vous en avez besoin. Pour enregistrer une matrice, tapez mata matsave filename matrixlist Remplacez filename par le nom du fichier que vous voulez créer. Stata ajoutera. mmat au nom de fichier automatiquement. Remplacez matrixlist par une ou plusieurs matrices que vous souhaitez enregistrer (en les séparant par des espaces) ou par un astérisque () pour enregistrer toutes les matrices actuellement en mémoire. Pour charger les matrices que vous avez enregistrées précédemment, tapez mata matuse nom_fichier Ceci chargera toutes les matrices stockées dans filename. Les deux commandes accepteront l'option de remplacement. Pour matsave. Cela permet à Mata de remplacer le fichier existant sur le disque. Pour matuse. Cela permet à Mata de remplacer les matrices existantes en mémoire avec les mêmes noms que les matrices dans le fichier. Ces commandes sont destinées à une utilisation interactive et ne peuvent pas être utilisées dans des fonctions. Si vous avez besoin d'enregistrer des matrices dans une fonction, consultez fopen. Fputmatrix. Fgetmatrix. Et fclose. Hierarchical Data Hierarchical data has always been a bit awkward to work with in Stata, or any other statistical program that uses a single data matrix. A typical example would be individuals living in households: should each household be one observation, or each individual Either way there are inefficiencies. In Mata you can have it both ways: one matrix of individuals and one matrix of households. The key is linking them together, but subscripts make that easy. As an example, take a look at the hh Stata data set. which is in Stata format. It consists of six individuals living in three households. hh is the household ID, hhType is the type of household, and hhInc is the household income. age and female are individual variables. This data is in the long form, with one observation for each individual, which means that the household variables must be duplicated. end use hh, replace l Now enter mata and load the hh Mata data set . mata mata matuse hh hh ind It contains two matrices, ind and hh. hh contains the household level variables ( hhType and hhInc ). ind contains the individual variables ( age and female ) plus the household ID. Note however, that hh does not contain an ID: the row number is an implicit ID. For example, if you wanted to know what type of household person number two lives in, youd use: ind2,3 is the household ID of the second person, or the row in the hh matrix. Column one of hh is the household type. Of course a regression model may need a single matrix just like Stata does. You can easily recreate the matrix as Stata views it with: Here ind.,3 is a column vector listing which row we want from hh for each row of ind. The resulting rows from hh are then placed next to ind to create x . Matrix Functions Mata has a very large number of matrix functions built into it. This section will hit some of the most useful. Creating Matrices The I function can take one or two arguments. If it is given one argument, it will return an identity matrix of size equal to the argument it was given. If it is given two arguments, it will return a matrix with that number of rows and columns which is full of zeroes except for ones along the principal diagonal. The J function creates a matrix of constants. It takes three arguments: the number of rows of the matrix to be created, the number of columns, and what to put in the matrix. The last argument can be of any type. The e function creates unit vectors: row vectors with a one in one column and zeroes everywhere else. It takes two arguments: the location of the one, and the size of the row vector. Thus you could create an identity matrix by combining e s, though the I function would of course be much easier. The uniform function returns a matrix filled with random numbers distributed uniform(0,1). The size is specified in the same way as with the J function. If youre putting together a matrix which will be symmetric, the makesymmetric function can take care of half the work for you. You put together the lower triangle, and makesymmetric will copy it to the upper triangle (replacing what was there before). It takes one argument, a matrix, and returns the symmetric version. x(1,2)(3,4) ymakesymmetric(x) y Theres a second version, makesymmetric which returns nothing but changes the input matrix instead: The sort function returns a sorted matrix. It takes two arguments: the matrix to sort, and the column(s) to sort by. Note that sort is not a quotstablequot sort. If there are any ties, they will be resolved randomly. Repeat sort(x,1) enough times and you should see some cases when the original second row becomes the first row and others where it stays the second row. If the second argument is a row vector, the matrix will be sorted by the first column listed, then ties resolved by the second column, etc. sort does not change the matrix it is given--it returns a copy. If youd prefer to sort the original matrix without making a copy, use sort . jumble and jumble are the opposite of sort and sort. They take just one argument, a matrix, and put its rows in a random order. Sizes of Matrices rows. cols. and length all take one argument, a matrix. They return the number of rows, the number of columns, and the total number of elements (rowscolumns) in that matrix respectively. rows(x) cols(x) length(x) These can be very useful in for loops where you want to loop over your entire matrix but dont know ahead of time what size it will be. Of course matrices can have missing values just like ordinary Stata data sets. If you need to know the number of missing values in the whole matrix, a row, or a column, use missing. rowmissing or colmissing respectively. missing returns a scalar, rowmissing returns a column vector (one value for each row in the matrix), and colmissing returns a row vector (one value for each column in the matrix). y(1,2,.)(4. 6)(7,8,.) missing(y) rowmissing (y) colmissing(y) To get the number of non-missing values, using nonmissing. rownonmissing. or colnonmissing . Descriptive Statistics Mata has a set of functions for calculating descriptive statistics, though by design its not as rich as Statas. In their simplest and most commonly used forms, all these functions take a single matrix as their argument. Sums may be stretching the definition of quotdescriptive statisticquot but they are very useful. There are three main sum functions: sum. rowsum. and colsum. sum adds up the whole matrix, returning a single number. rowsum adds up each row, returning a column vector. colsum adds up each column, returning a row vector. sum(x) rowsum(x) colsum(x) max and min simply return the largest or smallest element of the matrix. rowmax and rowmin return a column vector containing the largest or smallest element of each row. Likewise, colmax and colmin return a row vector. You can get the largest and smallest elements with the minmax functions, including minmax. rowminmax. and colminmax. They return both the min and the max in either two columns or, in the case of colminmax. two rows. Sometimes youre more interested in where the min or max is than what it is. If so, check out minindex and maxindex. The mean function returns a row vector containing the column means of the matrix. If you need row means, youll need to construct them yourself: You can also get the variance matrix of your matrix with variance, and the correlation matrix with correlation. Matrix Characteristics Mata has functions for finding the most common matrix characteristics. diagonal returns the principal diagonal of a matrix as a row vector. trace returns the sum of the diagonal elements. det returns the determinant (with some round-off error). rank returns the rank of the matrix. As a general rule, using rank to check that a matrix is full rank because a subsequent calculation requires it is redundant--better to let the subsequent calculation fail and handle the failure. Also, when determining the rank of a matrix on a computer a certain tolerance is required for round-off error. Different functions can use different tolerances, so they may disagree with the rank function. Solvers, Inverters and Decomposition Matrix solvers are functions designed to solve the equation AXB for X. Since inverting a matrix A can be done by solving the equation AXI, inverters and solvers are closely related. In addition, the solvers and inverters generally work by doing some sort of decomposition, and the decomposition methods can also be accessed directly. Thus there are several families of three related functions. Which family youll choose depends on the properties of your matrix. Well focus on Cholesky methods, but the others work in a very similar way. The Cholesky Decomposition decomposes a symmetric, positive definite matrix into a lower triangular matrix times its transpose. The results can be used to solve matrix equations and find inverses much more quickly than more general methods. To get an example matrix we can work with, we can take advantage of the fact that if x is of full rank, xx is symmetric and positive definite--and random matrices are all but certain to be full rank. So: The cholesky function takes one argument, a matrix, and returns a lower triangular matrix which is its Cholesky Decomposition. To verify that it works, note that is the same as a. To illustrate solving a matrix equation, we need a right-hand side. The cholsolve function takes two arguments, both matrices. It them sets up and solves the equation AXB where A is the first matrix and B is the second, returning X. To verify that it worked, note that The cholinv function takes one argument, a matrix, and returns its inverse: Again, to verify it worked try The result should be an identity matrix. Youll notice that round-off error makes some of the zeroes not quite zeroes, but its as close as you can get using a computer. If your matrix is square but not symmetric, LU Decomposition can do similar things (though its slower than Cholesky). The lud function is equivalent to cholesky. but more complex because it has to give back three results. Thus the matrices to store the results have to be passed in, similar to stview . LU Decomposition breaks a matrix into a lower triangular matrix L, an upper triangular matrix U, and a permutation matrix P. But Mata, instead of using a matrix P, gives a column vector p which can be used with subscripting to do the same thing. Take look at L. U. and p. To verify that it worked, see that is a. Note how were using subscripts to pull rows from a result, not an existing matrix, and yet it works just fine. lusolve and luinv are much simpler--in fact the usage is identical to cholsolv and cholinv. Try Similar functions exist for QR decomposition ( qrd. qrsolve. qrinv ). Singular value decomposition has svd and svsolve. but the related inverter is pinv (which returns the Moore-Penrose pseudoinverse). invsym. for inverting symmetric matrices, has no related decomposition or solver functions. It is, however, what Stata suggests for linear regression. Example: Linear Regression Youre now prepared to do the most common matrix manipulation of all, at least at the SSCC. Since we have the automobile data set loaded, lets regress price on mpg, rep78, foreign and weight to see which characteristics American consumers were willing to pay for in 1978. One complication is that rep78 is missing for some observations, so youll need to drop them from your regression. Of course you could just drop them from the data set entirely, but lets assume that you want to keep them for later use. The first step is to mark the observations you can actually use. Exit Mata by typing end. then create a new variable touse which is one if all the variables are non-missing and zero otherwise. gen touse(price. amp mpg. amp rep78. amp weight. amp foreign.) Of course in reality the only variable that is ever missing is rep78. but well pretend we didnt know that ahead of time. If you wanted to run a regression on a subpopulation (say, just the foreign cars) you could add a condition to mark the subsample too. Now go back into Mata by typing mata. Next make x a view onto all the independant variables and y a view onto the dependant variable. touse is the selection variable for both views: observations will only be included if it is equal to one. stview(x0. (quotmpgquot, quotrep78quot, quotweightquot, quotforeignquot), quottousequot) stview(y0. (quotpricequot), quottousequot) To include a constant term in the regression you need to add a column of ones to x. Use the J function to create it, then add it to x with the comma (column join) operator. Now you can find the betas: Of course they dont mean anything without standard errors. Start by finding the residuals: Then the variance-covariance matrix is The standard errors for each beta can be extracted using the diagonal function, along with sqrt. which takes the (element by element) square root. The t-statistic is the beta divided by the standard error, but this is an element by element division so you need to use the colon operator. To find the p-values requires the ttail function, which takes as arguments the degrees of freedom and the t-statistic and returns the probability. It is a single-tailed test however, so you need to multiply by two. To put your results together in a readable form, try: Now exit Mata again, and check your results against reg price mpg rep78 weight foreign They should be identical. In regular Stata, if is almost always used to define which observations a command should act on. Its the equivalent to SQLs where clause. In Mata, if is only used to control program flow. (Though Stata can use if in this way as well--see the appropriate section of Programming in Stata .) The most basic form of if is simply if ( condition ) statement If condition is true, then statement is executed. Otherwise it is skipped entirely. Note that the condition must be in parentheses. If you want to do more than one thing if the condition is true, use the following syntax: if ( condition ) statements You can also use else to specify things that should happen if the condition is not true. Thus you can create fairly elaborate structures: if ( condition1 ) statements1 else if ( condition2 ) statements2 else statements3 Keep in mind that each condition has a single result, either true or false. For example, If x is a matrix you cant write if (xgt5) and then list things you want done for those elements of x which are greater than 5. You can write if (x1,1gt5) followed by if (x1,2gt5) etc. but of course the easy way to do that is using a loop. Mata has while. do - while. and for loops available (plus goto for easier conversion of FORTRAN code, but we dont want to endorse spaghetti logic). while looks very similar to if: while ( condition ) statements The difference is that the statements will be executed over and over as long as the condition is true. Thus your first concern should be to make sure that at some point the condition will become false, or the loop will run forever. Note that x is shorthand for xx1. Even though we said xlt5, the final value of x is six. Thats because the loop only decides to end when x becomes six. You can also put a while loop with a single statement in a single line. This loop is perfectly legal, but it didnt do anything. The reason is that the condition started out false, so the loop never executed at all. Sometimes you need to make sure that a loop runs at least once, and thats a job for do-while. A do-while loop starts with do and ends with the while condition. The statements are always executed at least once. If the condition is true, the loop starts over again from the top. Note that x is increased to seven even though it started out greater than five. One typical use for do-while loops is to do something until it converges: do complex mathematical stuff while (abs(newvalue-oldvalue)gttolerance) But unless youre absolutely certain your process will actually converge, youd better put in an escape clause that tells it to stop after a while whether it converges or not: do complex mathematical stuff while (abs(newValue-oldValue)gttolerance amp iterationltmaxIterations) Recall our first while loop: This is such a common structure that programmers wanted a quicker way to construct it. The answer was for loops. The for loop equivalent to this while loop is Note the three components: an initialization step, a rule for when the loop should end, and some sort of progression towards that ending. Strictly speaking you can skip the initialization and the progression--just leave the semi-colons as placeholders. All this really means though is that youre promising to take care of those steps yourself. In particular x must already be defined and you need to make sure the loop will in fact end. By far the most common use of for loops is to loop over the elements of a matrix. Writing Your Own Functions Mata allows you to write your own functions--in fact many of the standard functions weve used are written in Mata. As youve seen, calling a function is a matter of typing the function name and then giving a list of arguments in parentheses. Defining a function follows the same structure: first the word function to tell Mata what youre doing, then a name, and then a list of arguments in parentheses. The body of the function follows in curly brackets. If you want your function to return a result, one of the statements in the body needs to be return. followed by the thing to return in parentheses. function myfunction(x, y) statements return(z) As an example, consider the following (not terribly useful) function. function doubleAndSum(x) xx2 return(sum(x)) This function takes a matrix, multiplies it by the scalar two, and returns the sum of all the elements in the matrix. To test it, try the following: mI(3) doubleAndSum(m) m Note that you passed in a matrix called m even though the function calls it x. Thats fine: the doubleAndSum function refers to whatever it is given as x. In fact the input doesnt even have to have a name. In the first case, the argument passed in is the result of the I function. In the second, it is a row vector defined on the spot. On the other hand, in these cases we cant see how the input matrix was doubled as they arent stored anywhere. Function arguments in Mata are quotpassed by reference. quot If a function changes one of the arguments it is given, that change persists even after the function is completed. Example: Loops and Functions Our next example comes from basic physics, but the real point is using loops and functions to get useful results. The classic equation for the motion of a body under uniform acceleration is simply Depending on the level of mathematics used in your last physics course, you may or may not have worked with that as a vector equation, where x, x0,v0 and a are vectors with one number for each dimension. The vector component makes this a good problem for Mata. Lets track and plot the movement of a falling object for ten seconds. Begin by defining a function x which takes x0,v0,a and t as arguments and returns the position of the body at time t. This is a good point to pause and test what weve done so far before moving on. Try: This represents a body just moving at 10 meterssecond (not that Mata cares about the units) in the positive x direction, so it will be easy to tell if your function works properly or not. should give 100,0,0. But that doesnt guarantee our acceleration term is right, so try This should give 0,0,50. Now well set up the actual values we want to examine: This is an object starting 500 meters up, moving to the right at 100 meters per second, and falling under normal earth gravity (about 9.8 meters per second squared). Note how we suddenly switched from three dimensions to two. Your function wont care in the slightest since theyre all still matrices, but its a lot easier to plot on a two dimensional graph. Now you need somewhere to put the results. Mata doesnt do graphs, so youll have to use Stata to plot them. But first we have to think about what the results will be. Your function provides a snapshot of the object at any given time, so well take a thousand snapshots spread across the ten second span. Each snapshot will have two numbers, an x coordinate and a y coordinate, so those will be your variables (though to Mata theyre just column one and column two of the x row vector). Get out of Mata, then use standard Stata commands to set up the observations and variables youll need. Now get back into Mata, and set up a view of these variables. Call it r (as in results): Now youre ready to loop over your 1000 snapshots and get the results of the x function for each one: Note how the time for each snapshot, i100, spreads them evenly across 10 seconds as i goes from 1 to 1000. Finally exit Mata again, and create the graph. end scatter y x Its the classic parabola of projectile motion as you no doubt expected, but of course the real point was to practice using functions and loops to generate and work with data. As soon as we defined the x() function, Mata compiled it into quotobject code. quot This is not quite the same as machine-language code that can be run all by itself. But it is something Mata can understand and run very quickly. If you were planning to use this function in the future you could save the object code. Then future programs wouldnt need to spend time compiling it. If this is something youre interested in, see the mlib and mata mosave commands. This example is contained in ex1.do. A pointer is a variable which contains the memory address of another variable or matrix. Thus it quotpointsquot to that other variable. In principle a pointer is just a number, but youll never work with the number directly. Instead, youll use two operators, amp and . Computer scientists call these the quotreferencequot and quotdereferencequot operators, but I like to think of them as quotthe address ofquot and quotthe thing at. quot Consider the following: First we define a matrix x so we have something to work with. Then p is defined as quotthe address of x. quot Thus p or quotthe thing at p quot is just another name for x. You can use subscripts with p just like you would with x. but note how you have to put p in parenthesis first. (p)2,2 means quotfind the thing at the address contained in p and get the value at row two, column two. quot p2,2 would mean quotget the value at row two, column two of p. and then find the thing at that addressquot which wont work because p is a scalar. Note that the matrix you are pointing to doesnt need to have a name. For example: makes p point to a 5x5 matrix of zeroes (since thats what J returns) even though theres no direct name for that matrix. Its only accessible as p. One use for pointers is to construct data structures Mata doesnt handle automatically. For example, you can construct a three dimensional matrix by making a two dimensional matrix of pointers, each of which points to a column vector. The first step is to define the matrix that will contain the pointers. Matrices cant switch between containing numbers and containing pointers, so you need to make sure that the matrix is defined as containing pointers. On the other hand, we dont have any actual pointers to store yet. Thus well set the initial values of the matrix to NULL. a special pointer that doesnt point to anything. Now loop over all the elements of x, and make each one a pointer to a new (and unique) column vector. To work with an element i, j,k of your three dimensional matrix youd use the following: Yes, the parentheses are essential. Its rather awkward though, so if you were going to work with such matrices a lot consider defining the following functions: function put(val, x,i, j,k) Usage: value to put, matrix to put it in, i, j, k to put it at. ((xi, j))k,1val function get(x, i,j, k) Usage: matrix to get from, i, j, k of value to get. return(((xi, j))k,1) Then you can do things like: The fact that you cant mix pointers and regular data within a matrix does limit your flexibility. You cant, for example, have a matrix of individual data including pointers to other data relevant to the individual. You can, however, have two parallel matrices, one containing numbers and the other containing pointers. If row i represents the same individual in both matrices, you can pull information from either or both as needed. Its also possible to create a pointer to a function. Given your existing function doubleAndSum() try: Note how Mata distinguishes between x() the function and x the variable by the parentheses, even though youre not passing in any arguments when you define a pointer. The main reason youd want to create a pointer to a function is so that you can use that pointer as the argument of a function. For example, Matas optimizer functions have you pass in a pointer to the function which is to be optimized. The Mata Optimizer Many statistical operations involve maximizing or minimizing some quantity--maximum likelihood estimation being the obvious example. Mata includes an optimizer for these operations. Matas optimizer is actually a family of functions which define and then solve an optimization problem. Evaluator functions The first function must be written by you: the function to be maximized or minimized. This function can do whatever you want, it may be very complex or very simple, but it must accept a certain set of arguments and return the proper result in order for the optimizer to use it. You can name the arguments whatever you like, but there must be the right number and each must have the proper meaning. Optimization problems are described using a variety of notations, but if we consider the problem of maximizing yf(x), the Mata version of f() must take the following arguments: a number indicating whether the function is supposed to calculate (0) just f(x), (1) yf(x) and f(x) or (2) f(x), f(x) and f(x) x (the thing that changes as the optimizer looks for the max) y (where f(x) will be stored) A variable to store f(x) if calculated A variable to store f(x) if calculated (often H since it is the hessian in multivariate problems) If you can find an analytic solution for f(x) and f(x) and code them in, Matas optimizer will be much faster and more accurate. This is often impractical though, and Mata is perfectly willing to find numeric approximations to the derivatives it needs. Note, however, that even if your function never calculates derivatives it must still accept variables where they can be stored. So lets try a very simple function: y-x4. If youre willing to let Mata find all the derivatives for you, you can code this as the following: Note that todo (the number telling the function whether to calculate derivatives or not), g. and H are completely unused, but must still be accepted. Note also that we could change all the names. We could call x Fred and y George as long as Georgef(Fred). If were not quite so lazy we can also code the derivatives for this function quite easily: In this case, both x and y were scalars, but youre not limited to scalars. Consider y-x14 - x24 The two xs are stored in a row vector x, so x1 is x1 and x2 is x2. Making sure the optimizer sends in the right size of x is one of the steps in setting it up. In many cases the quantity youll want to maximize will be the sum of a column. For example, in maximum likelihood you will probably create a column where each row gives an observations contribution to the likelihood function. Matas optimizer will do this automatically with the proper settings, so the previous function could be recast as: Note how the function had to define y as a column vector of the proper size--otherwise it is a scalar. In statistical applications the quantity to be maximized will depend not just on parameters that can vary (x in our problems thus far) but on data that do not vary. Matas optimizer can be set up to pass up to nine additional arguments to your evaluator function, which can contain the data. They go after the first two arguments (and before the final three). This calls for a change of variable names. Consider maximizing sf(b). Well now use x for the data matrix. Then the function definition would be: function f(todo, b, x, s, g, H) x can contain both the independent and dependant variables, but if its easier to work with a separate matrix y, then the definition becomes: function f(todo, b, x, y, s, g, H) Well do an example using this kind of evaluator shortly. Setting Up and Running an Optimization Problem Once youve got your evaluator function defined, youre ready to set up the optimization problem. The first step is to call the optimizeinit function. optimizeinit takes no arguments and returns a variable containing a description of your optimization problem. Youll never look at this description, but you will pass it in to all the other optimization functions. Next tell it where to find the evaluator: The first argument is the problem description, and the second is a pointer to the evaluator function you already defined. Now give it a starting value for x--remember the f() function is in the form yf(x). Of course the correct answer is zero, but we want it to do some work Now youre ready to actually run the optimizer: This returns the value of x which maximizes f(x). You may want to store this in a variable: If we want to use the g(x) function instead, theres one additional step. Recall that in g(x) we coded the first and second derivatives ourselves so Mata doesnt have to approximate them. Mata refers to this as a quotd2quot evaluator. A quotd1quot evaluator codes just the first derivative, and a quotd0quot evaluator codes no derivatives at all (the f(x) function is a d0 evaluator). Mata will assume functions are d0 unless we say otherwise, so you need to add: Note that the optimizer doesnt care what order all the initialization functions are called in, as long as theyre before the actual optimize(). What about h(x1, x2) Its identical to f(x), except that we need to set an initial value for both variables: In doing so we also tell Mata that future xs must have two columns. Finally, i(x1,x2), where the function to be maximized is the column sum of y, is what Mata calls a quotv0quot evaluator. The quotvquot is for vector, and the quot0quot again means that we didnt code any derivatives. Thus we need To see the complete code to run the optimizer with each evaluator, see the the last parts of mataclass. do. There is one setup function we havent needed to call but you should know: changes the problem from maximizing the function (the default) to minimizing it. Example: Ranking Teams As a final, extended example, consider a problem familiar to any sports fan: determining how good a team is based on its wonloss record. Well assume that a team can be characterized by a single quotstrengthquot variable s. If team i plays team j, well assume that the probability of team i winning is given by exp(si-sj)(1exp(si-sj)), better known to Stata as invlogit(si-sj). Then, given a record of games played and who won, we can find a set of values for s that maximizes the probability of the given outcome. Well do a Monte Carlo study by first creating data which fits our assumptions, and then seeing how well the method works. Creating the Data The first step is to create the data. This is an exercise in matrix manipulation, so if you want to focus on the optimization part of the problem feel free to skip ahead. On the other hand, most readers will benefit from some practice in this area. First create a row vector str containing the real strengths of each team. For simplicity, use the uniform function, giving strengths distributed uniform(0,1). For our example well make 50 teams: Note that the column number within the str vector acts as a sort of team ID. Next we need a way to keep track of who played who. Well create a two-column matrix, where each row is a game and the two columns will contain the IDs of the two teams who played in that game. For brevity well call the team in column one the quothomequot team and the team in column two the quotvisitingquot team. Well assume that each team plays 20 games, 10 as the home team and 10 as the visiting team. Begin by creating a column vector teams containing the 50 teams using the range operator: Now create a column vector season which is just ten copies of teams stacked on top of each other: seasonteams for(i1ilt10i) seasonseasonteams This represents the home teams. Next assign the visiting teams by taking the same vector, putting it in a random order, and column joining it to the original: The only trouble is, its entirely possible for a team to be randomly assigned to play itself. This wouldnt really bother our estimator, but it does offend any claims that this represents the real world. More importantly, fixing it is good practice. Create a column vector same with the same number of rows as season which contains a 1 if the home and visiting teams are the same and a 0 if they are not: If a game has the a team playing itself, we will swap the visiting team with the visiting team of a randomly chosen game. Since its possible we might get the same team yet again, well keep checking and swapping until there are no more games between the same team. Heres the code: while (max(same)1) for(i1 iltrows(season) i) if (samei) swaptrunc(uniform(1,1)rows(season))1 tempseasonswap,2 seasonswap,2seasoni,2 seasoni,2temp same(season.,1:season.,2) Note how max(same) will be zero if there are no longer any games where the home and visiting teams are the same, so thats how we know when were done. We then loop over the rows, stopping to change those where samei is one (or true). In those cases, we pick a random row and swap visiting teams with it, using a temp variable to store its visiting teams ID as we do. We then recalculate same based on the new version of season before the while condition is reevaluated. Now we need to decide who won each game. Well create a column vector winner, which will contain a 1 if the home team won and a zero if the visiting team won. winnerJ(rows(season),1,.) for(i1 iltrows(season) i) winneriuniform(1,1):ltinvlogit(strseasoni,1-strseasoni,2) Note how indexing is used to pull up the strength ( str ) of the appropriate team--well be doing that a lot. The Maximum Likelihood Estimator Now were ready to construct the (log) likelihood function to be maximized. Well start with a version thats easy to understand, and try to make it efficient later. function llf(todo, strhat, season, winner, llf, g,H) llfJ(rows(season),1,.) for(i1iltrows(season)i) if (winneri) llfilog(invlogit(strhatseasoni,1-strhatseasoni,2)) else llfilog(invlogit(strhatseasoni,2-strhatseasoni,1)) This will be a v0 evaluator which takes season and winner as additional arguments. The estimated strengths are stored in strhat, and the column of log likelihoods (which will be summed automatically by virtue of being v0) is stored in llf . We have two possible outcomes, and the formula for finding the log likelihood is different in each outcome. For now well handle the two possibilities with an ifelse structure, but there are more efficient ways. Now to set up the optimization problem: soptimizeinit() optimizeinitevaluator(s, ampllf()) optimizeinitevaluatortype(s, quotv0quot) strhat0J(1,rows(teams),.5) optimizeinitparams(s, strhat0) optimizeinitargument(s,1,season) optimizeinitargument(s,2,winner) strhat1optimize(s) Most of these youve seen before. Note that strhat0 is the vector of starting values for our estimate of str. Since the actual strengths are distributed uniform(0,1) well start by setting them all to 0.5. What is new is optimizeinitarguments. This is where you tell the optimizer to pass in season and winner to your evaluator. As you see optimizeinitarguments takes three arguments: the optimization problem, the number of the argument youre setting, and what to pass in. Run the code. It will take a while but it should work. Efficiency So how can we make it faster It would be nice if we didnt have to figure out which formula to use for the likelihood. So lets rearrange the data a bit: instead of column one being the quothomequot team and column two the quotvisitingquot team, terms which have no real meaning in our model, lets make column one the winner and column two the loser. Create a new matrix season2 with the new arrangement: season2J(rows(season),2,.) for(i1iltrows(season)i) if (winneri) season2i,.seasoni,. else season2i,.seasoni,(2,1) Of course this loop takes time to run, but it only runs once. Its the evaluator that must be run over and over, so taking a bit more time to set things up so that the evaluator runs faster is well worth it. One general principle when it comes to writing fast Mata code is that matrix operations are faster than loops you write out. Theres no matrix operation that would allow you to look in one matrix for the estimated strength of a team identified in another matrix, but you can take calculating the log and invlogit functions out of the loop. Heres a second and more efficient version of the evaluator function: function llf2(todo, strhat, season, llf, g,H) xJ(rows(season),1,.) for(i1iltrows(season)i) xistrhatseasoni,1-strhatseasoni,2 llflog(invlogit(x)) Note how it doesnt need to have the winner matrix passed in anymore--it expects a version of season ( season2 ) that conveys that information by which team is in column one. Heres the setup needed to run this version: soptimizeinit() optimizeinitevaluator(s, ampllf2()) optimizeinitevaluatortype(s, quotv0quot) strhat0J(1,rows(teams),.5) optimizeinitparams(s, strhat0) optimizeinitargument(s,1,season2) strhat2optimize(s) Youll see that this runs in about half the time of the original. Most of the gain comes from moving the calculation of log and invlogit out of the loop. For those looking for the absolute best performance, consider turning on matastrict ( mata set matastrict on ). Matastrict requires that you declare the names and types of all variables before using them rather than letting Mata choose. Mata has more variable types than most languages, and they can be confusing. On the other hand, declaring your variables can help you avoid errors. More importantly, Matas compiler can use the additional information to create slightly more efficient object code. If you are interested in using matastrict, see the manuals and especially the section on declarations. Constraints One characteristic of this model is that only the difference between teams is identified. You could add 100 or -1,000,000 to all the strengths and the probability of each outcome would remain the same. Thus two different runs on the same data could give very different numbers and both be right. However, if we constrain just one strength to be a given number, then all the strengths are identified. Matas optimizer accepts constraints on the parameters in the form of two matrices C and c. The parameters p are then constrained such that Cpc . Lets constrain the strength of team one to be zero. To implement this, the C matrix needs to be a row vector with a column for each team. It will have a one in the first column and a zero in all other columns, which makes it a unit vector. c will be simply the scalar zero. You then pass in this constraint using the optimizeinitconstraints function. It takes two arguments: the problem s. as usual, and then a matrix which is the row join of C and c. Im not sure why it doesnt just take them as two separate arguments, but its easy to join them. Since youve made no other changes to the problem, you can simply run it again by calling optimize. This version will actually run significantly faster. As an exercise, consider constructing some sort of metric for how well your estimator does. (One easy one would be how often it correctly identifies the best team.) Then vary the number of games per season and see how many it takes to get reasonable accuracy. However, dont do this if you want to continue to take the ranking systems of actual sports seriously. This example (with additional commands for timing each method) is found in ex2.do. Learning More This article has just scratched the surface of whats possible in Mata. Theres obviously much more to learn, and even more to be looked up when you need it. As usual, Stata Corp. has included most of the Mata documentation in the online help. There is one trick though: to get help for Mata you need to type help mata topic rather than just help topic. This is especially important for functions and such that exist in both Mata and Stata. For example, compare the results of the following: help abs help mata abs A couple useful starting places: help mata help mata functions The Mata manuals are available in the CDE Library and the 4218 lab. There are two books, but they should be thought of as two volumes of the same manual. You are also welcome to ask the Help Desk for assistance. Mata is new to us as well, but well try to figure things out together. Last Revised: 10242007


No comments:

Post a Comment