logo Netzschleuder network catalog, repository, and centrifuge

History of patentsview

The changes to the source code of this entry in the repository, newest first, each with the differences it made to the entry's files. They are also listed on GitLab.

[entries] Add the date when each entry was added, and remove icon_hash by Tiago de Paula Peixoto beff7c9
The dates are those of the commits that first added the entries' files
(2020-08-11 for the entries of the initial commit); renamed entries keep
the date of their first name.

Changed: none
diff --git a/entries/patentsview/__init__.py b/entries/patentsview/__init__.py
index 6519ba1..745e8c6 100644
--- a/entries/patentsview/__init__.py
+++ b/entries/patentsview/__init__.py
@@ -70,7 +70,7 @@ url = ['https://huggingface.co/datasets/zalizedata/us-patents-citation-company-d
        'https://patentsview.org/']
 citation = [('PatentsView (U.S. Patent and Trademark Office); packaged by DataForge, "US Patents, Citations & Assignee Graph (USPTO / PatentsView)." Zenodo (2026)',
              'https://doi.org/10.5281/zenodo.21812658')]
-icon_hash = None
+date_added = '2026-10-31'
 # DataForge: CC BY-NC 4.0 for its curated layer; the PatentsView data
 # themselves are under CC BY 4.0
 upstream_license = ("CC BY-NC 4.0 (DataForge copy; PatentsView data: CC BY 4.0)",
[entries] Prefix the properties in the descriptions with (Node), (Edge) or (Graph) by Tiago de Paula Peixoto bc3dbbd
The lists of properties at the end of the descriptions marked edge
properties with "Edge" but left node properties unmarked, or grouped
them in "Nodes: `a`, ...; `b`, ..." items, so the kind of a property
was often unclear. Every item now starts with (Node), (Edge) or (Graph),
followed by the property names, a colon and the explanation, one item
per property or group of properties; qualifications (kinds of nodes,
networks) follow the names in parentheses. Properties that were only
named got a short explanation, and a few items that named the wrong
kind of property were corrected.
diff --git a/entries/patentsview/__init__.py b/entries/patentsview/__init__.py
index 50eb126..6519ba1 100644
--- a/entries/patentsview/__init__.py
+++ b/entries/patentsview/__init__.py
@@ -37,18 +37,33 @@ The texts of the patents (abstracts) and the derived statistics of DataForge (ci
 
 The networks have the following properties:
 
-- `is_patent` (bipartite networks): whether the node is a patent (otherwise an inventor, assignee or CPC group).
-- `name`: the patent number (e.g. `10000000`, `D1006496` for design patents, `RE49999` for reissues), the PatentsView identifier of the inventor or of the assignee, the CPC group (e.g. `H04L63/0428`), or the name of the company group.
-- Patents (`citations`): `title`, `patent_type` (`utility`, `design`, `plant`, `reissue`, ...), `wipo_kind` (the kind code, e.g. `B2`), `grant_date` and `filing_date` (Unix time, -1 if unknown), `num_claims` (-1 if unknown), `withdrawn`, `cpc_subclass` (the primary CPC subclass), `wipo_field` (the WIPO technology field), `assignee` (the harmonized name of the first assignee), `assignee_country`, `inventor_country` (the country of the first inventor). In the bipartite networks, patents have only their `name`.
-- Edge `date` (`citations`): the date of the cited patent given in the citation (Unix time, -1 if unknown).
-- Edge `category` (`citations`): who gave the citation: `cited by applicant`, `cited by examiner`, `cited by other`, `cited by third party`, `imported from a related application`, or empty if unknown.
-- Inventors: `first_name`, `last_name`, `country` (of their first record).
-- Edge `sequence` (bipartite networks): the position of the inventor, assignee or CPC group in the list of the patent.
-- Assignees: `assignee_name`, `name_harmonized`, `group` (the company group of DataForge), `is_individual`, `assignee_type` (the USPTO assignee type code, e.g. 2 for a U.S. company, 3 for a foreign company, 6 for the U.S. government), `country`, `state`, `city`.
-- CPC groups: `section`, `class`, `subclass`.
-- Edge `cpc_type` (`cpc`): `inventional` or `additional`.
-- Company groups (`company_citations`): `n_patents`, `first_grant_year`, `last_grant_year`, `country`, `top_cpc_subclasses` (from the company profiles of DataForge; empty, or -1, if missing).
-- Edge `weight`, `first_year`, `last_year` (`company_citations`): the number of citations, and the first and last year of the citations."""
+- (Node) `is_patent` (bipartite networks): whether the node is a patent (otherwise an inventor, assignee or CPC group).
+- (Node) `name`: the patent number (e.g. `10000000`, `D1006496` for design patents, `RE49999` for reissues), the PatentsView identifier of the inventor or of the assignee, the CPC group (e.g. `H04L63/0428`), or the name of the company group.
+- (Node) `title` (patents, `citations`): the title of the patent.
+- (Node) `patent_type` (patents, `citations`): `utility`, `design`, `plant`, `reissue`, ...
+- (Node) `wipo_kind` (patents, `citations`): the kind code, e.g. `B2`.
+- (Node) `grant_date`, `filing_date` (patents, `citations`): the dates of grant and filing (Unix time, -1 if unknown).
+- (Node) `num_claims` (patents, `citations`): the number of claims (-1 if unknown).
+- (Node) `withdrawn` (patents, `citations`): whether the patent was withdrawn.
+- (Node) `cpc_subclass` (patents, `citations`): the primary CPC subclass.
+- (Node) `wipo_field` (patents, `citations`): the WIPO technology field.
+- (Node) `assignee` (patents, `citations`): the harmonized name of the first assignee.
+- (Node) `assignee_country` (patents, `citations`): the country of the first assignee.
+- (Node) `inventor_country` (patents, `citations`): the country of the first inventor.
+- (Node) In the bipartite networks, patents have only their `name`.
+- (Edge) `date` (`citations`): the date of the cited patent given in the citation (Unix time, -1 if unknown).
+- (Edge) `category` (`citations`): who gave the citation: `cited by applicant`, `cited by examiner`, `cited by other`, `cited by third party`, `imported from a related application`, or empty if unknown.
+- (Node) `first_name`, `last_name`, `country` (inventors): the name and the country of the inventor (of their first record).
+- (Edge) `sequence` (bipartite networks): the position of the inventor, assignee or CPC group in the list of the patent.
+- (Node) `assignee_name`, `name_harmonized` (assignees): the name of the assignee, as given and harmonized.
+- (Node) `group` (assignees): the company group of DataForge.
+- (Node) `is_individual` (assignees): whether the assignee is an individual.
+- (Node) `assignee_type` (assignees): the USPTO assignee type code, e.g. 2 for a U.S. company, 3 for a foreign company, 6 for the U.S. government.
+- (Node) `country`, `state`, `city` (assignees): the location of the assignee.
+- (Node) `section`, `class`, `subclass` (CPC groups): the CPC section, class and subclass of the group.
+- (Edge) `cpc_type` (`cpc`): `inventional` or `additional`.
+- (Node) `n_patents`, `first_grant_year`, `last_grant_year`, `country`, `top_cpc_subclasses` (company groups, `company_citations`): the number of patents, the years of the first and last grants, the country and the top CPC subclasses of the group, from the company profiles of DataForge (empty, or -1, if missing).
+- (Edge) `weight`, `first_year`, `last_year` (`company_citations`): the number of citations, and the first and last year of the citations."""
 tags = ['Informational', 'Citation', 'Collaboration', 'Affiliation', 'Bipartite', 'Unweighted', 'Metadata']
 url = ['https://huggingface.co/datasets/zalizedata/us-patents-citation-company-dataset',
        'https://data.zalize.com/datasets/us-patents-citation-company-dataset',
[entries] New entry: patentsview by Tiago de Paula Peixoto 9e0534e
diff --git a/entries/patentsview/__init__.py b/entries/patentsview/__init__.py
new file mode 100644
index 0000000..50eb126
--- /dev/null
+++ b/entries/patentsview/__init__.py
@@ -0,0 +1,263 @@
+#! /usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2026 Tiago de Paula Peixoto <tiago@skewed.de>
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Affero General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Affero General Public License along
+# with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+
+import pyarrow
+import pyarrow.parquet as pq
+import pyarrow.compute as pc
+
+from .. import *
+
+title = "U.S. patents: citations, inventors, assignees and classes (PatentsView, 1976-2026)"
+description = r"""The utility, design, plant and reissue patents granted by the U.S. Patent and Trademark Office (USPTO) since 1976, their citations, inventors, assignees and technology classes, from the bulk data of PatentsView (the patent data platform of the USPTO), in a third-party copy: the tables were downloaded from PatentsView, processed and redistributed on Hugging Face by DataForge (data.zalize.com), as of August 2026. (PatentsView's own downloads now require an API key of the USPTO Open Data Portal.) The entry `us_patents` has the earlier citation network of 1975-1999 of the NBER.
+
+- `citations`: the citation network: a directed edge goes from a patent to each patent it cites (U.S. patents only; the citations of foreign patents and of the scientific literature are not included). Cited patents that are not in the table of patents (e.g. granted before 1976) are nodes without metadata.
+- `inventors`: the undirected bipartite network of the patents and their inventors, as disambiguated by PatentsView.
+- `assignees`: the undirected bipartite network of the patents and their assignees (the owners of the patents: companies, universities, government agencies, individuals), as disambiguated by PatentsView.
+- `cpc`: the undirected bipartite network of the patents and the groups of the Cooperative Patent Classification (CPC) to which they belong.
+- `company_citations`: the citations between companies, aggregated by DataForge: a directed edge goes from a company group (the assignees harmonized and grouped by company by DataForge) to a company group whose patents its patents cite, weighted by the number of citations (only the pairs with at least a minimum number of citations given by DataForge).
+
+The texts of the patents (abstracts) and the derived statistics of DataForge (citation metrics, trends per class) are left out.
+
+The networks have the following properties:
+
+- `is_patent` (bipartite networks): whether the node is a patent (otherwise an inventor, assignee or CPC group).
+- `name`: the patent number (e.g. `10000000`, `D1006496` for design patents, `RE49999` for reissues), the PatentsView identifier of the inventor or of the assignee, the CPC group (e.g. `H04L63/0428`), or the name of the company group.
+- Patents (`citations`): `title`, `patent_type` (`utility`, `design`, `plant`, `reissue`, ...), `wipo_kind` (the kind code, e.g. `B2`), `grant_date` and `filing_date` (Unix time, -1 if unknown), `num_claims` (-1 if unknown), `withdrawn`, `cpc_subclass` (the primary CPC subclass), `wipo_field` (the WIPO technology field), `assignee` (the harmonized name of the first assignee), `assignee_country`, `inventor_country` (the country of the first inventor). In the bipartite networks, patents have only their `name`.
+- Edge `date` (`citations`): the date of the cited patent given in the citation (Unix time, -1 if unknown).
+- Edge `category` (`citations`): who gave the citation: `cited by applicant`, `cited by examiner`, `cited by other`, `cited by third party`, `imported from a related application`, or empty if unknown.
+- Inventors: `first_name`, `last_name`, `country` (of their first record).
+- Edge `sequence` (bipartite networks): the position of the inventor, assignee or CPC group in the list of the patent.
+- Assignees: `assignee_name`, `name_harmonized`, `group` (the company group of DataForge), `is_individual`, `assignee_type` (the USPTO assignee type code, e.g. 2 for a U.S. company, 3 for a foreign company, 6 for the U.S. government), `country`, `state`, `city`.
+- CPC groups: `section`, `class`, `subclass`.
+- Edge `cpc_type` (`cpc`): `inventional` or `additional`.
+- Company groups (`company_citations`): `n_patents`, `first_grant_year`, `last_grant_year`, `country`, `top_cpc_subclasses` (from the company profiles of DataForge; empty, or -1, if missing).
+- Edge `weight`, `first_year`, `last_year` (`company_citations`): the number of citations, and the first and last year of the citations."""
+tags = ['Informational', 'Citation', 'Collaboration', 'Affiliation', 'Bipartite', 'Unweighted', 'Metadata']
+url = ['https://huggingface.co/datasets/zalizedata/us-patents-citation-company-dataset',
+       'https://data.zalize.com/datasets/us-patents-citation-company-dataset',
+       'https://patentsview.org/']
+citation = [('PatentsView (U.S. Patent and Trademark Office); packaged by DataForge, "US Patents, Citations & Assignee Graph (USPTO / PatentsView)." Zenodo (2026)',
+             'https://doi.org/10.5281/zenodo.21812658')]
+icon_hash = None
+# DataForge: CC BY-NC 4.0 for its curated layer; the PatentsView data
+# themselves are under CC BY 4.0
+upstream_license = ("CC BY-NC 4.0 (DataForge copy; PatentsView data: CC BY 4.0)",
+                    "https://creativecommons.org/licenses/by-nc/4.0/")
+upstream_prefix = 'https://huggingface.co/datasets/zalizedata/us-patents-citation-company-dataset/resolve/b8537c7b1d9fce238f0a73ba6de84d6f88787b91'
+
+def _shards(table, n):
+    return [f"data/{table}/{table}-{i:05d}-of-{n:05d}.parquet" for i in range(n)]
+
+_patent_files = _shards("patents", 6)
+_tables = {"citations": _shards("citations", 2),
+           "inventors": _shards("inventors", 2),
+           "assignees": _shards("assignees", 1),
+           "cpc": _shards("cpc", 2),
+           "company_citations": _shards("company_citations", 1) +
+                                _shards("company_profiles", 1)}
+files = [(tuple(fs + (_patent_files if alt == "citations" else [])), alt, None)
+         for alt, fs in _tables.items()]
+
+def fetch_upstream(force=False):
+    return fetch_upstream_files(__name__.split(".")[-1], upstream_prefix, files,
+                                force)
+
+# For checks only: if set, only (about) this many rows of each table are read
+_check_rows = None
+
+def read_table(name, fnames, columns):
+    tables, n = [], 0
+    for fname in fnames:
+        with open_upstream_file(name, fname, "rb", seekable=True) as f:
+            pf = pq.ParquetFile(f)
+            if _check_rows is None:
+                tables.append(pf.read(columns=columns))
+            else:
+                for b in pf.iter_batches(batch_size=min(_check_rows, 1 << 16),
+                                         columns=columns):
+                    tables.append(pyarrow.Table.from_batches([b]))
+                    n += b.num_rows
+                    if n >= _check_rows:
+                        break
+        if _check_rows is not None and n >= _check_rows:
+            break
+    return pyarrow.concat_tables(tables)
+
+def date_array(col):
+    "A date32 column as Unix times (-1 if missing)."
+    x = pc.cast(pc.cast(col, pyarrow.int32()), pyarrow.int64()).fill_null(-1).to_numpy().copy()
+    x[x >= 0] *= 86400
+    return x
+
+def string_vp(g, offset, vals, name):
+    p = g.vp[name] if name in g.vp else g.new_vp("string")
+    for i, x in enumerate(vals):
+        if x:
+            p[offset + i] = x
+    g.vp[name] = p
+
+def categorical_ep(g, col, name):
+    d = col.combine_chunks().dictionary_encode()
+    codes = g.new_ep("int", vals=d.indices.fill_null(-1).to_numpy())
+    labels = d.dictionary.to_pylist()
+    p = g.new_ep("string")
+    map_property_values(codes, p, lambda i: "" if i < 0 else labels[i])
+    g.ep[name] = p
+
+def index_of(col, values):
+    return pc.index_in(col, value_set=values).to_numpy(zero_copy_only=False)
+
+@cache_network()
+@coerce_props()
+@annotate()
+def parse(alts=None):
+    name = __name__.split(".")[-1]
+    for fnames, alt, fmt in files:
+        if alts is not None and alt not in alts:
+            continue
+        fs = _tables[alt]
+        if alt == "company_citations":
+            t = read_table(name, fs[:1], None)
+            prof = read_table(name, fs[1:], None)
+            groups = pc.unique(pyarrow.concat_arrays(
+                [t.column("citing_group").combine_chunks(),
+                 t.column("cited_group").combine_chunks()]))
+            g = Graph(directed=True)
+            g.add_vertex(len(groups))
+            g.add_edge_list(numpy.column_stack(
+                [index_of(t.column("citing_group"), groups),
+                 index_of(t.column("cited_group"), groups)]))
+            string_vp(g, 0, groups.to_pylist(), "name")
+            g.ep.weight = g.new_ep("int64_t", vals=t.column("n_citations").to_numpy())
+            g.ep.first_year = g.new_ep("int", vals=t.column("first_year").fill_null(-1).to_numpy())
+            g.ep.last_year = g.new_ep("int", vals=t.column("last_year").fill_null(-1).to_numpy())
+            idx = pc.index_in(groups, value_set=prof.column("company_group")).fill_null(-1).to_numpy()
+            for k in ("n_patents", "first_grant_year", "last_grant_year"):
+                vals = prof.column(k).fill_null(-1).to_numpy()
+                p = g.new_vp("int64_t")
+                p.a = numpy.where(idx >= 0, vals[numpy.maximum(idx, 0)], -1)
+                g.vp[k] = p
+            for k in ("country", "top_cpc_subclasses"):
+                vals = prof.column(k).to_pylist()
+                string_vp(g, 0, [vals[i] if i >= 0 else "" for i in idx], k)
+            yield alt, g
+            continue
+
+        if alt == "citations":
+            t = read_table(name, fs, ["citing_patent_id", "cited_patent_id",
+                                      "citation_date", "citation_category"])
+            pat = read_table(name, _patent_files,
+                             ["patent_id", "title", "patent_type", "wipo_kind",
+                              "grant_date", "filing_date", "num_claims",
+                              "withdrawn", "cpc_primary_subclass", "wipo_field",
+                              "first_assignee_name_harmonized",
+                              "assignee_country", "first_inventor_country"])
+            ids = pat.column("patent_id").combine_chunks()
+            extra = pc.unique(pyarrow.concat_arrays(
+                [t.column("citing_patent_id").combine_chunks(),
+                 t.column("cited_patent_id").combine_chunks()]))
+            extra = pc.filter(extra, pc.invert(pc.is_in(extra, value_set=ids)))
+            nodes = pyarrow.concat_arrays([ids, extra])
+            g = Graph(directed=True)
+            g.add_vertex(len(nodes))
+            g.add_edge_list(numpy.column_stack(
+                [index_of(t.column("citing_patent_id"), nodes),
+                 index_of(t.column("cited_patent_id"), nodes)]))
+            string_vp(g, 0, nodes.to_pylist(), "name")
+            N = len(ids)
+            for k, c in (("title", "title"), ("patent_type", "patent_type"),
+                         ("wipo_kind", "wipo_kind"),
+                         ("cpc_subclass", "cpc_primary_subclass"),
+                         ("wipo_field", "wipo_field"),
+                         ("assignee", "first_assignee_name_harmonized"),
+                         ("assignee_country", "assignee_country"),
+                         ("inventor_country", "first_inventor_country")):
+                string_vp(g, 0, pat.column(c).to_pylist(), k)
+            for k in ("grant_date", "filing_date"):
+                p = g.new_vp("int64_t")
+                p.a[N:] = -1
+                p.a[:N] = date_array(pat.column(k))
+                g.vp[k] = p
+            g.vp.num_claims = g.new_vp("int")
+            g.vp.num_claims.a[N:] = -1
+            g.vp.num_claims.a[:N] = pat.column("num_claims").fill_null(-1).to_numpy()
+            g.vp.withdrawn = g.new_vp("bool")
+            g.vp.withdrawn.a[:N] = pat.column("withdrawn").fill_null(False).to_numpy(zero_copy_only=False)
+            del pat
+            g.ep.date = g.new_ep("int64_t", vals=date_array(t.column("citation_date")))
+            categorical_ep(g, t.column("citation_category"), "category")
+            yield alt, g
+            continue
+
+        # bipartite networks
+        if alt == "inventors":
+            cols = ["patent_id", "inventor_sequence", "inventor_id",
+                    "inventor_name_first", "inventor_name_last",
+                    "inventor_country"]
+            key, seq = "inventor_id", "inventor_sequence"
+            props = [("first_name", "inventor_name_first"),
+                     ("last_name", "inventor_name_last"),
+                     ("country", "inventor_country")]
+        elif alt == "assignees":
+            cols = ["patent_id", "assignee_sequence", "assignee_id",
+                    "assignee_name", "is_individual", "assignee_type",
+                    "assignee_name_harmonized", "assignee_group",
+                    "assignee_country", "assignee_state", "assignee_city"]
+            key, seq = "assignee_id", "assignee_sequence"
+            props = [("assignee_name", "assignee_name"),
+                     ("name_harmonized", "assignee_name_harmonized"),
+                     ("group", "assignee_group"),
+                     ("country", "assignee_country"),
+                     ("state", "assignee_state"), ("city", "assignee_city")]
+        else:
+            cols = ["patent_id", "cpc_sequence", "cpc_section", "cpc_class",
+                    "cpc_subclass", "cpc_group", "cpc_type"]
+            key, seq = "cpc_group", "cpc_sequence"
+            props = [("section", "cpc_section"), ("class", "cpc_class"),
+                     ("subclass", "cpc_subclass")]
+        t = read_table(name, fs, cols)
+        t = t.filter(pc.and_(pc.is_valid(t.column(key)),
+                             pc.is_valid(t.column("patent_id"))))
+        pd = t.column("patent_id").combine_chunks().dictionary_encode()
+        od = t.column(key).combine_chunks().dictionary_encode()
+        pidx = pd.indices.to_numpy()
+        oidx = od.indices.to_numpy()
+        Np = len(pd.dictionary)
+        g = Graph(directed=False)
+        g.add_vertex(Np + len(od.dictionary))
+        g.add_edge_list(numpy.column_stack([pidx, Np + oidx]))
+        g.vp.is_patent = g.new_vp("bool")
+        g.vp.is_patent.a[:Np] = 1
+        string_vp(g, 0, pd.dictionary.to_pylist(), "name")
+        string_vp(g, Np, od.dictionary.to_pylist(), "name")
+        _, first = numpy.unique(oidx, return_index=True)
+        first = pyarrow.array(first)
+        for k, c in props:
+            string_vp(g, Np, t.column(c).take(first).to_pylist(), k)
+        if alt == "assignees":
+            g.vp.is_individual = g.new_vp("bool")
+            g.vp.is_individual.a[Np:] = t.column("is_individual").take(first).fill_null(False).to_numpy(zero_copy_only=False)
+            g.vp.assignee_type = g.new_vp("int")
+            g.vp.assignee_type.a[:Np] = -1
+            g.vp.assignee_type.a[Np:] = t.column("assignee_type").take(first).fill_null(-1).to_numpy()
+        g.ep.sequence = g.new_ep("int", vals=t.column(seq).fill_null(-1).to_numpy())
+        if alt == "cpc":
+            categorical_ep(g, t.column("cpc_type"), "cpc_type")
+        yield alt, g