{"action":"created","comment":{"url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/pulls/comments/64017433","id":64017433,"diff_hunk":"@@ -71,49 +69,50 @@ contrasts_matrix(C::MyContrasts, baseind, n) = ...\n \"\"\"\n abstract AbstractContrasts\n \n-## Contrasts + Data = ContrastsMatrix\n-type ContrastsMatrix{T}\n+# Contrasts + Levels (usually from data) = ContrastsMatrix\n+type ContrastsMatrix{T, S <: AbstractContrasts}\n     matrix::Matrix{Float64}\n     termnames::Vector{T}\n     levels::Vector{T}\n-    contrasts::AbstractContrasts\n+    contrasts::S\n end\n \n \"\"\"\n-    ContrastsMatrix{T}(::AbstractContrasts, levels::Vector{T})\n+    ContrastsMatrix{T}(C::AbstractContrasts, levels::Vector{T})\n \n-Instantiate contrasts matrix for given data (categorical levels)\n+Compute contrasts matrix for a given set of categorical data levels.\n \n If levels are specified in the `AbstractContrasts`, those will be used, and likewise\n for the base level (which defaults to the first level).\n \"\"\"\n-function ContrastsMatrix{T}(C::AbstractContrasts, lvls::Vector{T})\n-\n-    ## if levels are defined on C, use those, validating that they line up.\n-    ## what does that mean?\n-    ##\n-    ## C.levels == lvls (best case)\n-    ## data levels missing from contrast: would generate empty/undefined rows. \n-    ## better to filter data frame first\n-    ## contrast levels missing from data: would have empty columns, generate a\n-    ## rank-deficient model matrix.\n-    c_lvls = convert(typeof(lvls), get(C.levels, lvls))\n-    mismatched_lvls = symdiff(c_lvls, lvls)\n-    isempty(mismatched_lvls) || error(\"Contrasts levels not found in data or vice-versa: \", mismatched_lvls)\n-\n-    n = length(c_lvls)\n-    n > 1 || error(\"not enough degrees of freedom to define contrasts\")\n-    \n-    ## find index of base level. use C.base, then default (1).\n-    baseind = isnull(C.base) ? 1 : findfirst(c_lvls, convert(eltype(lvls), get(C.base)))\n-    baseind > 0 || error(\"Base level $(C.base) not found in levels\")\n+function ContrastsMatrix{T}(C::AbstractContrasts, levels::Vector{T})\n+\n+    # if levels are defined on C, use those, validating that they line up.\n+    # what does that mean? either:\n+    #\n+    # 1. C.levels == levels (best case)\n+    # 2. data levels missing from contrast: would generate empty/undefined rows. \n+    #    better to filter data frame first\n+    # 3. contrast levels missing from data: would have empty columns, generate a\n+    #    rank-deficient model matrix.\n+    c_levels = oftype(levels, get(C.levels, levels))\n+    mismatched_levels = symdiff(c_levels, levels)\n+    isempty(mismatched_levels) || error(\"contrasts levels not found in data or vice-versa: $mismatched_levels.\\nData levels: $levels.\\nContrast levels: $c_levels\")\n+\n+    n = length(c_levels)\n+    n == 0 && error(\"empty set of levels found (need at least two to compute contrasts).\")\n+    n == 1 && error(\"only one level found: $(c_levels[1]). need at least two to compute contrasts.\")\n     \n     not_base = [1:(baseind-1); (baseind+1):n]\n     tnames = c_lvls[not_base]\n+    # find index of base level. use C.base, then default (1).\n+    baseind = isnull(C.base) ? 1 : findfirst(c_levels, convert(eltype(levels), get(C.base)))","path":"src/statsmodels/contrasts.jl","position":null,"original_position":148,"commit_id":"d84fa7348e275501da890223394f053ed7073c0f","original_commit_id":"bed5964512b7b5b8918ef516e5551f618ff7a0f9","user":{"login":"nalimilan","id":1120448,"avatar_url":"https://avatars.githubusercontent.com/u/1120448?v=3","gravatar_id":"","url":"https://api.github.com/users/nalimilan","html_url":"https://github.com/nalimilan","followers_url":"https://api.github.com/users/nalimilan/followers","following_url":"https://api.github.com/users/nalimilan/following{/other_user}","gists_url":"https://api.github.com/users/nalimilan/gists{/gist_id}","starred_url":"https://api.github.com/users/nalimilan/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nalimilan/subscriptions","organizations_url":"https://api.github.com/users/nalimilan/orgs","repos_url":"https://api.github.com/users/nalimilan/repos","events_url":"https://api.github.com/users/nalimilan/events{/privacy}","received_events_url":"https://api.github.com/users/nalimilan/received_events","type":"User","site_admin":false},"body":"I though we decided to get rid of the `convert(eltype(levels), ...)` stuff?\r\n\r\nAlso, a single empty line is enough inside a function.","created_at":"2016-05-20T09:59:42Z","updated_at":"2016-05-20T09:59:42Z","html_url":"https://github.com/JuliaStats/DataFrames.jl/pull/870#discussion_r64017433","pull_request_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/pulls/870","_links":{"self":{"href":"https://api.github.com/repos/JuliaStats/DataFrames.jl/pulls/comments/64017433"},"html":{"href":"https://github.com/JuliaStats/DataFrames.jl/pull/870#discussion_r64017433"},"pull_request":{"href":"https://api.github.com/repos/JuliaStats/DataFrames.jl/pulls/870"}}},"pull_request":{"url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/pulls/870","id":45514275,"html_url":"https://github.com/JuliaStats/DataFrames.jl/pull/870","diff_url":"https://github.com/JuliaStats/DataFrames.jl/pull/870.diff","patch_url":"https://github.com/JuliaStats/DataFrames.jl/pull/870.patch","issue_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/issues/870","number":870,"state":"open","locked":false,"title":"RFC: contrast coding","user":{"login":"kleinschmidt","id":135920,"avatar_url":"https://avatars.githubusercontent.com/u/135920?v=3","gravatar_id":"","url":"https://api.github.com/users/kleinschmidt","html_url":"https://github.com/kleinschmidt","followers_url":"https://api.github.com/users/kleinschmidt/followers","following_url":"https://api.github.com/users/kleinschmidt/following{/other_user}","gists_url":"https://api.github.com/users/kleinschmidt/gists{/gist_id}","starred_url":"https://api.github.com/users/kleinschmidt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kleinschmidt/subscriptions","organizations_url":"https://api.github.com/users/kleinschmidt/orgs","repos_url":"https://api.github.com/users/kleinschmidt/repos","events_url":"https://api.github.com/users/kleinschmidt/events{/privacy}","received_events_url":"https://api.github.com/users/kleinschmidt/received_events","type":"User","site_admin":false},"body":"This PR introduces a system for contrast coding, or controlling how categorical variables are converted into columns in a `ModelMatrix`.  The basic interface is that the `ModelFrame` constructor takes an optional keyword argument `contrasts`, which is a `Dict` mapping column name symbols to contrasts, specified as subtypes of `AbstractContrast` or instances thereof.  This addresses (at least partially) #757 and #788.\r\n\r\nThe code could be cleaned up quite a bit and refactored, but I wanted to get feedback on the general approach so far.  It also still doesn't address the problem of needing to switch contrast coding based on whether or not lower-order effects are also present (also raised in #757), but I'm planning on also implementing those checks.","created_at":"2015-09-21T04:50:48Z","updated_at":"2016-05-20T09:59:42Z","closed_at":null,"merged_at":null,"merge_commit_sha":"af54b882e8f8c3cdede1355b99d085a2872bacf5","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/pulls/870/commits","review_comments_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/pulls/870/comments","review_comment_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/pulls/comments{/number}","comments_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/issues/870/comments","statuses_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/statuses/d84fa7348e275501da890223394f053ed7073c0f","head":{"label":"kleinschmidt:dfk/contrasts","ref":"dfk/contrasts","sha":"d84fa7348e275501da890223394f053ed7073c0f","user":{"login":"kleinschmidt","id":135920,"avatar_url":"https://avatars.githubusercontent.com/u/135920?v=3","gravatar_id":"","url":"https://api.github.com/users/kleinschmidt","html_url":"https://github.com/kleinschmidt","followers_url":"https://api.github.com/users/kleinschmidt/followers","following_url":"https://api.github.com/users/kleinschmidt/following{/other_user}","gists_url":"https://api.github.com/users/kleinschmidt/gists{/gist_id}","starred_url":"https://api.github.com/users/kleinschmidt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kleinschmidt/subscriptions","organizations_url":"https://api.github.com/users/kleinschmidt/orgs","repos_url":"https://api.github.com/users/kleinschmidt/repos","events_url":"https://api.github.com/users/kleinschmidt/events{/privacy}","received_events_url":"https://api.github.com/users/kleinschmidt/received_events","type":"User","site_admin":false},"repo":{"id":22589796,"name":"DataFrames.jl","full_name":"kleinschmidt/DataFrames.jl","owner":{"login":"kleinschmidt","id":135920,"avatar_url":"https://avatars.githubusercontent.com/u/135920?v=3","gravatar_id":"","url":"https://api.github.com/users/kleinschmidt","html_url":"https://github.com/kleinschmidt","followers_url":"https://api.github.com/users/kleinschmidt/followers","following_url":"https://api.github.com/users/kleinschmidt/following{/other_user}","gists_url":"https://api.github.com/users/kleinschmidt/gists{/gist_id}","starred_url":"https://api.github.com/users/kleinschmidt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kleinschmidt/subscriptions","organizations_url":"https://api.github.com/users/kleinschmidt/orgs","repos_url":"https://api.github.com/users/kleinschmidt/repos","events_url":"https://api.github.com/users/kleinschmidt/events{/privacy}","received_events_url":"https://api.github.com/users/kleinschmidt/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/kleinschmidt/DataFrames.jl","description":"library for working with tabular data in Julia","fork":true,"url":"https://api.github.com/repos/kleinschmidt/DataFrames.jl","forks_url":"https://api.github.com/repos/kleinschmidt/DataFrames.jl/forks","keys_url":"https://api.github.com/repos/kleinschmidt/DataFrames.jl/keys{/key_id}","collaborators_url":"https://api.github.com/repos/kleinschmidt/DataFrames.jl/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/kleinschmidt/DataFrames.jl/teams","hooks_url":"https://api.github.com/repos/kleinschmidt/DataFrames.jl/hooks","issue_events_url":"https://api.github.com/repos/kleinschmidt/DataFrames.jl/issues/events{/number}","events_url":"https://api.github.com/repos/kleinschmidt/DataFrames.jl/events","assignees_url":"https://api.github.com/repos/kleinschmidt/DataFrames.jl/assignees{/user}","branches_url":"https://api.github.com/repos/kleinschmidt/DataFrames.jl/branches{/branch}","tags_url":"https://api.github.com/repos/kleinschmidt/DataFrames.jl/tags","blobs_url":"https://api.github.com/repos/kleinschmidt/DataFrames.jl/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/kleinschmidt/DataFrames.jl/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/kleinschmidt/DataFrames.jl/git/refs{/sha}","trees_url":"https://api.github.com/repos/kleinschmidt/DataFrames.jl/git/trees{/sha}","statuses_url":"https://api.github.com/repos/kleinschmidt/DataFrames.jl/statuses/{sha}","languages_url":"https://api.github.com/repos/kleinschmidt/DataFrames.jl/languages","stargazers_url":"https://api.github.com/repos/kleinschmidt/DataFrames.jl/stargazers","contributors_url":"https://api.github.com/repos/kleinschmidt/DataFrames.jl/contributors","subscribers_url":"https://api.github.com/repos/kleinschmidt/DataFrames.jl/subscribers","subscription_url":"https://api.github.com/repos/kleinschmidt/DataFrames.jl/subscription","commits_url":"https://api.github.com/repos/kleinschmidt/DataFrames.jl/commits{/sha}","git_commits_url":"https://api.github.com/repos/kleinschmidt/DataFrames.jl/git/commits{/sha}","comments_url":"https://api.github.com/repos/kleinschmidt/DataFrames.jl/comments{/number}","issue_comment_url":"https://api.github.com/repos/kleinschmidt/DataFrames.jl/issues/comments{/number}","contents_url":"https://api.github.com/repos/kleinschmidt/DataFrames.jl/contents/{+path}","compare_url":"https://api.github.com/repos/kleinschmidt/DataFrames.jl/compare/{base}...{head}","merges_url":"https://api.github.com/repos/kleinschmidt/DataFrames.jl/merges","archive_url":"https://api.github.com/repos/kleinschmidt/DataFrames.jl/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/kleinschmidt/DataFrames.jl/downloads","issues_url":"https://api.github.com/repos/kleinschmidt/DataFrames.jl/issues{/number}","pulls_url":"https://api.github.com/repos/kleinschmidt/DataFrames.jl/pulls{/number}","milestones_url":"https://api.github.com/repos/kleinschmidt/DataFrames.jl/milestones{/number}","notifications_url":"https://api.github.com/repos/kleinschmidt/DataFrames.jl/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/kleinschmidt/DataFrames.jl/labels{/name}","releases_url":"https://api.github.com/repos/kleinschmidt/DataFrames.jl/releases{/id}","deployments_url":"https://api.github.com/repos/kleinschmidt/DataFrames.jl/deployments","created_at":"2014-08-04T02:41:23Z","updated_at":"2014-08-30T04:30:06Z","pushed_at":"2016-05-13T23:25:27Z","git_url":"git://github.com/kleinschmidt/DataFrames.jl.git","ssh_url":"git@github.com:kleinschmidt/DataFrames.jl.git","clone_url":"https://github.com/kleinschmidt/DataFrames.jl.git","svn_url":"https://github.com/kleinschmidt/DataFrames.jl","homepage":null,"size":10124,"stargazers_count":0,"watchers_count":0,"language":"Julia","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"JuliaStats:master","ref":"master","sha":"40a57d32399ca0360d41ec9205f483af85575a59","user":{"login":"JuliaStats","id":2761531,"avatar_url":"https://avatars.githubusercontent.com/u/2761531?v=3","gravatar_id":"","url":"https://api.github.com/users/JuliaStats","html_url":"https://github.com/JuliaStats","followers_url":"https://api.github.com/users/JuliaStats/followers","following_url":"https://api.github.com/users/JuliaStats/following{/other_user}","gists_url":"https://api.github.com/users/JuliaStats/gists{/gist_id}","starred_url":"https://api.github.com/users/JuliaStats/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/JuliaStats/subscriptions","organizations_url":"https://api.github.com/users/JuliaStats/orgs","repos_url":"https://api.github.com/users/JuliaStats/repos","events_url":"https://api.github.com/users/JuliaStats/events{/privacy}","received_events_url":"https://api.github.com/users/JuliaStats/received_events","type":"Organization","site_admin":false},"repo":{"id":4992873,"name":"DataFrames.jl","full_name":"JuliaStats/DataFrames.jl","owner":{"login":"JuliaStats","id":2761531,"avatar_url":"https://avatars.githubusercontent.com/u/2761531?v=3","gravatar_id":"","url":"https://api.github.com/users/JuliaStats","html_url":"https://github.com/JuliaStats","followers_url":"https://api.github.com/users/JuliaStats/followers","following_url":"https://api.github.com/users/JuliaStats/following{/other_user}","gists_url":"https://api.github.com/users/JuliaStats/gists{/gist_id}","starred_url":"https://api.github.com/users/JuliaStats/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/JuliaStats/subscriptions","organizations_url":"https://api.github.com/users/JuliaStats/orgs","repos_url":"https://api.github.com/users/JuliaStats/repos","events_url":"https://api.github.com/users/JuliaStats/events{/privacy}","received_events_url":"https://api.github.com/users/JuliaStats/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/JuliaStats/DataFrames.jl","description":"library for working with tabular data in Julia","fork":false,"url":"https://api.github.com/repos/JuliaStats/DataFrames.jl","forks_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/forks","keys_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/keys{/key_id}","collaborators_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/teams","hooks_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/hooks","issue_events_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/issues/events{/number}","events_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/events","assignees_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/assignees{/user}","branches_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/branches{/branch}","tags_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/tags","blobs_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/git/refs{/sha}","trees_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/git/trees{/sha}","statuses_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/statuses/{sha}","languages_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/languages","stargazers_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/stargazers","contributors_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/contributors","subscribers_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/subscribers","subscription_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/subscription","commits_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/commits{/sha}","git_commits_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/git/commits{/sha}","comments_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/comments{/number}","issue_comment_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/issues/comments{/number}","contents_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/contents/{+path}","compare_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/compare/{base}...{head}","merges_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/merges","archive_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/downloads","issues_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/issues{/number}","pulls_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/pulls{/number}","milestones_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/milestones{/number}","notifications_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/labels{/name}","releases_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/releases{/id}","deployments_url":"https://api.github.com/repos/JuliaStats/DataFrames.jl/deployments","created_at":"2012-07-11T18:00:09Z","updated_at":"2016-05-14T02:48:48Z","pushed_at":"2016-05-19T18:02:47Z","git_url":"git://github.com/JuliaStats/DataFrames.jl.git","ssh_url":"git@github.com:JuliaStats/DataFrames.jl.git","clone_url":"https://github.com/JuliaStats/DataFrames.jl.git","svn_url":"https://github.com/JuliaStats/DataFrames.jl","homepage":null,"size":10447,"stargazers_count":279,"watchers_count":279,"language":"Julia","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":140,"mirror_url":null,"open_issues_count":169,"forks":140,"open_issues":169,"watchers":279,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/JuliaStats/DataFrames.jl/pulls/870"},"html":{"href":"https://github.com/JuliaStats/DataFrames.jl/pull/870"},"issue":{"href":"https://api.github.com/repos/JuliaStats/DataFrames.jl/issues/870"},"comments":{"href":"https://api.github.com/repos/JuliaStats/DataFrames.jl/issues/870/comments"},"review_comments":{"href":"https://api.github.com/repos/JuliaStats/DataFrames.jl/pulls/870/comments"},"review_comment":{"href":"https://api.github.com/repos/JuliaStats/DataFrames.jl/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/JuliaStats/DataFrames.jl/pulls/870/commits"},"statuses":{"href":"https://api.github.com/repos/JuliaStats/DataFrames.jl/statuses/d84fa7348e275501da890223394f053ed7073c0f"}}}}
{"actor":{"display_login":"nalimilan"}}