Answers.Body: <p>I had created a python package called <a href="https://pypi.org/project/pgnhelper/" rel="noreferrer">pgnhelper</a> with <a href="https://pgnhelper.readthedocs.io/en/latest/index.html" rel="noreferrer">documentation</a> which can be used to see what you would like to find.</p>
  <p>Do not use a big pgn file as it will take more time. This is more useful for examining stats of a tournament. 5 or so tournament pgn files can be combined. Player names should be consistent.</p>
  <h3>Typical setup for windows 10</h3>
  <ol>
  <li><p>Intall python 3.7 or later from <a href="https://www.python.org/downloads/" rel="noreferrer">https://www.python.org/downloads/</a></p>
  </li>
  <li><p>Install pgnhelper from command line.</p>
  </li>
  </ol>
  <pre><code>pip install pgnhelper -U
  </code></pre>
  <ol start="3">
  <li>Save the code below to ruylopez.py.</li>
  </ol>
  <p>3.1 Download candidates games from <a href="https://theweekinchess.com/assets/files/pgn/wchcand22.pgn" rel="noreferrer">https://theweekinchess.com/assets/files/pgn/wchcand22.pgn</a></p>
  <p>3.2. Place the pgn file and ruylopez.py in the same directory.</p>
  <ol start="4">
  <li>Execute ruylopez.py from command line like an example below.</li>
  </ol>
  <pre><code>PS F:\pgnhelpter_test&gt; python ruylopez.py
  </code></pre>
  <p>The ruylopez.py and wchcand22.pgn are in F:\pgnhelpter_test path where <code>pgnhelpter_test</code> is the folder or directory name.</p>
  <h3>Code</h3>
  <p><code>ruylopez.py</code></p>
  <pre><code>&quot;&quot;&quot;Show player names and number of games on the given opening name.
  
  requirements:
    pip install pgnhelper -U
  &quot;&quot;&quot;
  
  
  import pgnhelper
  import pandas as pd
  
  
  # opening_name = 'Nimzo-Indian'
  opening_name = 'Ruy Lopez'
  
  pgnfn = 'wchcand22.pgn'
  # https://theweekinchess.com/assets/files/pgn/wchcand22.pgn
  
  df, players, israting = pgnhelper.record.get_pgn_data(pgnfn)
  
  # print(df)
  # df.to_csv(&quot;sample.csv&quot;, index=False)
  
  openings = df.Opening.unique()
  for o in openings:
      print(o)
  
  data = {}
  for p in players:
      data1 = {}
      for o in openings:
          dfw = df.loc[(df.Opening == o) &amp; (df.White == p)]
          dfb = df.loc[(df.Opening == o) &amp; (df.Black == p)]
          wcnt = len(dfw)
          bcnt = len(dfb)
          total = wcnt + bcnt
          data1.update({o: {'w': wcnt, 'b': bcnt, 'total': total}})
  
      data.update({p: {'data': data1}})
  
  mydata = []
  for p in players:
      mydata.append([opening_name, p,
                     data[p]['data'][opening_name]['w'],
                     data[p]['data'][opening_name]['b'],
                     data[p]['data'][opening_name]['total']])
  
  mydf = pd.DataFrame(
      mydata,
      columns=['Opening', 'Player', 'Wgames', 'Bgames', 'Total'])
  
  mydf = mydf.sort_values(by=['Total', 'Wgames'], ascending=[False, False])
  print(mydf)
  
  mydf.to_csv(&quot;ruylopez.csv&quot;, index=False)  # Save to csv file
  </code></pre>
  <h3>Output</h3>
  <pre><code>Sicilian defence
  English opening
  Ruy Lopez
  QGD
  Sicilian, Chekhover variation
  Giuoco Pianissimo
  Gruenfeld
  Sicilian
  Catalan
  Nimzo-Indian
  Catalan opening
  Petrov
  Reti
  Four knights game
  Four knights
  English
  Giuoco Piano
  QGD semi-Slav
       Opening               Player  Wgames  Bgames  Total
  2  Ruy Lopez     Nakamura, Hikaru       2       4      6
  7  Ruy Lopez     Rapport, Richard       4       1      5
  0  Ruy Lopez     Caruana, Fabiano       3       2      5
  1  Ruy Lopez    Radjabov, Teimour       1       3      4
  3  Ruy Lopez    Firouzja, Alireza       1       1      2
  6  Ruy Lopez          Ding, Liren       0       2      2
  4  Ruy Lopez  Nepomniachtchi, Ian       1       0      1
  5  Ruy Lopez  Duda, Jan-Krzysztof       1       0      1
  </code></pre>
  <p>The code can be revised to show a column of score percentage. Can also be revised to show by ECO code.</p>
  <p>Opening names in the game are printed in console due to:</p>
  <pre><code>openings = df.Opening.unique()
  for o in openings:
      print(o)
  </code></pre>
  <p>Results are printed in console due to:</p>
  <pre><code>print(mydf)
  </code></pre>
  <p>csv file will be saved due to:</p>
  <p><code>mydf.to_csv(&quot;ruylopez.csv&quot;, index=False)  # Save to csv file</code></p>
  <p>You can change the opening name in  the code by changing below code:</p>
  <pre><code>opening_name = 'Ruy Lopez'
  </code></pre>
  <p>You can use different pgn file but be sure the game has Opening tag like below.</p>
  <pre><code>[Event &quot;FIDE Candidates 2022&quot;]
  [Site &quot;Madrid ESP&quot;]
  [Date &quot;2022.06.17&quot;]
  [Round &quot;1.3&quot;]
  [White &quot;Caruana, Fabiano&quot;]
  [Black &quot;Nakamura, Hikaru&quot;]
  [Result &quot;1-0&quot;]
  [WhiteTitle &quot;GM&quot;]
  [BlackTitle &quot;GM&quot;]
  [WhiteElo &quot;2783&quot;]
  [BlackElo &quot;2760&quot;]
  [ECO &quot;C65&quot;]
  [Opening &quot;Ruy Lopez&quot;]
  [Variation &quot;Berlin defence&quot;]
  [WhiteFideId &quot;2020009&quot;]
  [BlackFideId &quot;2016192&quot;]
  [EventDate &quot;2022.06.17&quot;]
  
  1. e4 e5 2. Nf3 Nc6 ...
  </code></pre>
  <p>There must be <code>Opening</code> tag.</p>
  <pre><code>[Opening &quot;Ruy Lopez&quot;]
  </code></pre>
  <h3>Add eco</h3>
  <p>If the game in your pgn file has no Opening tag, you can use pgnhelper to add a tag.</p>
  <p>Example from command line:</p>
  <pre><code>pgnhelper addeco --inpgnfn candidates_zurich_1953.pgn --outpgnfn eco_candidates_zurich_1953.pgn --inecopgnfn eco.pgn
  </code></pre>
  <p>See also the guide at <a href="https://pgnhelper.readthedocs.io/en/latest/usage.html" rel="noreferrer">https://pgnhelper.readthedocs.io/en/latest/usage.html</a>.</p>
  <p>The file <code>eco.pgn</code> is needed, you can <a href="https://github.com/fsmosca/pgnhelper/tree/main/eco" rel="noreferrer">download</a> it from github.</p>
  <p>For example you can download pgn files from <a href="https://theweekinchess.com/" rel="noreferrer">weekinchess,</a> or from <a href="https://www.pgnmentor.com/files.html#events" rel="noreferrer">pgnmentor.</a></p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-08-07T17:17:04.590Z
Answers.Text: This is excellent.  Great job breaking it down into accessible steps.  (+1)
Answers.UserDisplayName: SecretAgentMan
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-08-08T18:23:14.623Z
Answers.Text: Have you tried running with pypy? If most of your computation is pure python it could speed things up. But if it's pandas than you won't get any benefit.
Answers.UserDisplayName: qwr
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-08-08T23:40:05.797Z
Answers.Text: I have not yet tried it with pypy. Will try it and compare the speed at some point when I have time.
Answers.UserDisplayName: ferdy
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-07-16T04:47:41.940Z
Answers.LastActivityDate: 2022-07-16T04:47:41.940Z
Answers.UserDisplayName: ferdy
Answers.Body: <p>I'm not sure any of these solutions below provide exactly what you're looking for, but I think enough functionality is there to assist you in your goal. Though the second option is very similar to the <a href="https://www.365chess.com/opening.php?m=4&amp;n=74&amp;ms=e4.e5.d4&amp;ns=3.5.74" rel="nofollow noreferrer">Chess365 functionality</a> you reference.</p>
  <p><strong>Option 1: ChessGames.com General Search</strong><br />
  <a href="https://www.chessgames.com/" rel="nofollow noreferrer">ChessGames.com</a> allows searches by ECO code or opening.   For example, <a href="https://www.chessgames.com/perl/chess.pl?yearcomp=exactly&amp;year=2021&amp;playercomp=either&amp;pid=&amp;player=&amp;pid2=&amp;player2=&amp;movescomp=exactly&amp;moves=&amp;opening=C45&amp;eco=&amp;result=" rel="nofollow noreferrer">here are the results</a> for games in the <a href="https://en.wikipedia.org/wiki/Scotch_Game" rel="nofollow noreferrer">Scotch</a> (ECOs C45–45) restricted to the year 2021. You can further restrict games by result (White wins, Black wins, draw, or &quot;no draw&quot;). You can parse the results easily enough.</p>
  <p><strong>Option 2: ChessGames.com Opening Explorer</strong><br />
  ChessGames.com also has an opening explorer that will list around 6 practitioners of that opening ECO code (3 with the White pieces, and 3 with Black). For example, searching ECO code 65 (<a href="https://en.wikipedia.org/wiki/Berlin_Defence_(chess)" rel="nofollow noreferrer">Berlin Defense</a> is 65–67) gives the following.</p>
  <p><a href="https://i.sstatic.net/eTO3f.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/eTO3f.png" alt="Results from search" /></a></p>
  <p><strong>Option 3: ChessTempo.com Opening Explorer</strong><br />
  <a href="https://chesstempo.com/" rel="nofollow noreferrer">ChessTempo.com</a> has an <a href="https://old.chesstempo.com/game-database.html" rel="nofollow noreferrer">opening explorer</a> with some added filters including specifying a rating range. Again, you'd have to parse the results, but it seems relevant.</p>
  <p>For example, I asked for all games with position after <strong>1. e4 c5 2. Nc3 Nc6 3. f4</strong> (<a href="https://en.wikipedia.org/wiki/Sicilian_Defence#Grand_Prix_Attack" rel="nofollow noreferrer">Grand Prix Attack</a>) with both players rated 2700+.  It returns the following.</p>
  <p><a href="https://i.sstatic.net/64KFI.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/64KFI.png" alt="Search results from ChessTempo" /></a></p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-07-18T06:22:05.150Z
Answers.Text: Basically what I want is like your option 2, but with a longer list of players
Answers.UserDisplayName: Brian Cheung
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-07-15T16:39:25.417Z
Answers.LastActivityDate: 2022-08-07T17:18:07.343Z
Answers.LastEditDate: 2022-08-07T17:18:07.343Z
Answers.UserDisplayName: SecretAgentMan
Answers.Body: <p>You could use <code>pgn-extract -e3 pgn-file-name</code> to split the pgn file by ECO codes of games, e.g., you will get files C60.pgn to C99.pgn for Ruy Lopez. You can then combine C60.pgn to C99.pgn to get a single Ruy Lopez file. You may also be able to export from scid vs pc games in a range of ECO codes. You can then simply browse the file in scid vs pc. Or extract games of a specific player (again using pgn-extract) and you will see how many games are extracted. Otherwise, you can use a &quot;simple&quot; bash (e.g., grep/sort/wc commands)/awk/sed/perl/python script to get player frequencies in a pgn file. (Sorry, I cannot write such a script quickly, but similar scripts may be available already.)</p>
  <p>If you are more interested in a specific player, then extract first by player name and then get the statistics of their openings. (By the way, pgn-extract can add opening codes in a pgn file of they don't already exist.)</p>
  <p>Or in scid vs pc filter games containing a given position, say, the position after 1. e4 e5 2. Nf3 Nc6 3. Bb5, and browse the filtered list.</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-08-08T03:35:00.010Z
Answers.LastActivityDate: 2022-08-08T16:19:14.277Z
Answers.LastEditDate: 2022-08-08T16:19:14.277Z
Answers.UserDisplayName: chesskobra
Body: <p>Is there a convenient way to search for players by their opening? For example if I input 'Ruy Lopez' then it gives me a list of chess players, sorted by how many times they played Ruy Lopez in tournament.</p>
  <p>I know that chess.com and 365chess has this feature, but they only provide 3 to 5 players per opening.</p>
  
Tags: <opening><database>
Title: How to search for chess players by favourite opening
ThreadText: # How to search for chess players by favourite opening
  
  (Asked by: username_0 on 2022-07-15)
  
  Is there a convenient way to search for players by their opening? For example if I input 'Ruy Lopez' then it gives me a list of chess players, sorted by how many times they played Ruy Lopez in tournament.
  
  I know that chess.com and 365chess has this feature, but they only provide 3 to 5 players per opening.
  
  **Tags:** opening, database
  
  
  ---
  
  ## 3 answers
  
  ### Answer by username_1 on 2022-07-16. Score: 5
  
  I had created a python package called pgnhelper with documentation which can be used to see what you would like to find.
  Do not use a big pgn file as it will take more time. This is more useful for examining stats of a tournament. 5 or so tournament pgn files can be combined. Player names should be consistent.
  Typical setup for windows 10
  
  Intall python 3.7 or later from https://www.python.org/downloads/
  
  Install pgnhelper from command line.
  
  
  pip install pgnhelper -U
  
  
  Save the code below to ruylopez.py.
  
  3.1 Download candidates games from https://theweekinchess.com/assets/files/pgn/wchcand22.pgn
  3.2. Place the pgn file and ruylopez.py in the same directory.
  
  Execute ruylopez.py from command line like an example below.
  
  PS F:\pgnhelpter_test> python ruylopez.py
  
  The ruylopez.py and wchcand22.pgn are in F:\pgnhelpter_test path where pgnhelpter_test is the folder or directory name.
  Code
  ruylopez.py
  """Show player names and number of games on the given opening name.
  
  requirements:
    pip install pgnhelper -U
  """
  
  
  import pgnhelper
  import pandas as pd
  
  
  # opening_name = 'Nimzo-Indian'
  opening_name = 'Ruy Lopez'
  
  pgnfn = 'wchcand22.pgn'
  # https://theweekinchess.com/assets/files/pgn/wchcand22.pgn
  
  df, players, israting = pgnhelper.record.get_pgn_data(pgnfn)
  
  # print(df)
  # df.to_csv("sample.csv", index=False)
  
  openings = df.Opening.unique()
  for o in openings:
      print(o)
  
  data = {}
  for p in players:
      data1 = {}
      for o in openings:
          dfw = df.loc[(df.Opening == o) & (df.White == p)]
          dfb = df.loc[(df.Opening == o) & (df.Black == p)]
          wcnt = len(dfw)
          bcnt = len(dfb)
          total = wcnt + bcnt
          data1.update({o: {'w': wcnt, 'b': bcnt, 'total': total}})
  
      data.update({p: {'data': data1}})
  
  mydata = []
  for p in players:
      mydata.append([opening_name, p,
                     data[p]['data'][opening_name]['w'],
                     data[p]['data'][opening_name]['b'],
                     data[p]['data'][opening_name]['total']])
  
  mydf = pd.DataFrame(
      mydata,
      columns=['Opening', 'Player', 'Wgames', 'Bgames', 'Total'])
  
  mydf = mydf.sort_values(by=['Total', 'Wgames'], ascending=[False, False])
  print(mydf)
  
  mydf.to_csv("ruylopez.csv", index=False)  # Save to csv file
  
  Output
  Sicilian defence
  English opening
  Ruy Lopez
  QGD
  Sicilian, Chekhover variation
  Giuoco Pianissimo
  Gruenfeld
  Sicilian
  Catalan
  Nimzo-Indian
  Catalan opening
  Petrov
  Reti
  Four knights game
  Four knights
  English
  Giuoco Piano
  QGD semi-Slav
       Opening               Player  Wgames  Bgames  Total
  2  Ruy Lopez     Nakamura, Hikaru       2       4      6
  7  Ruy Lopez     Rapport, Richard       4       1      5
  0  Ruy Lopez     Caruana, Fabiano       3       2      5
  1  Ruy Lopez    Radjabov, Teimour       1       3      4
  3  Ruy Lopez    Firouzja, Alireza       1       1      2
  6  Ruy Lopez          Ding, Liren       0       2      2
  4  Ruy Lopez  Nepomniachtchi, Ian       1       0      1
  5  Ruy Lopez  Duda, Jan-Krzysztof       1       0      1
  
  The code can be revised to show a column of score percentage. Can also be revised to show by ECO code.
  Opening names in the game are printed in console due to:
  openings = df.Opening.unique()
  for o in openings:
      print(o)
  
  Results are printed in console due to:
  print(mydf)
  
  csv file will be saved due to:
  mydf.to_csv("ruylopez.csv", index=False)  # Save to csv file
  You can change the opening name in  the code by changing below code:
  opening_name = 'Ruy Lopez'
  
  You can use different pgn file but be sure the game has Opening tag like below.
  [Event "FIDE Candidates 2022"]
  [Site "Madrid ESP"]
  [Date "2022.06.17"]
  [Round "1.3"]
  [White "Caruana, Fabiano"]
  [Black "Nakamura, Hikaru"]
  [Result "1-0"]
  [WhiteTitle "GM"]
  [BlackTitle "GM"]
  [WhiteElo "2783"]
  [BlackElo "2760"]
  [ECO "C65"]
  [Opening "Ruy Lopez"]
  [Variation "Berlin defence"]
  [WhiteFideId "2020009"]
  [BlackFideId "2016192"]
  [EventDate "2022.06.17"]
  
  1. e4 e5 2. Nf3 Nc6 ...
  
  There must be Opening tag.
  [Opening "Ruy Lopez"]
  
  Add eco
  If the game in your pgn file has no Opening tag, you can use pgnhelper to add a tag.
  Example from command line:
  pgnhelper addeco --inpgnfn candidates_zurich_1953.pgn --outpgnfn eco_candidates_zurich_1953.pgn --inecopgnfn eco.pgn
  
  See also the guide at https://pgnhelper.readthedocs.io/en/latest/usage.html.
  The file eco.pgn is needed, you can download it from github.
  For example you can download pgn files from weekinchess, or from pgnmentor.
  
  > **Comments:**
  > **username_2**: This is excellent.  Great job breaking it down into accessible steps.  (+1)  
  > **username_3**: Have you tried running with pypy? If most of your computation is pure python it could speed things up. But if it's pandas than you won't get any benefit.  
  > **username_1**: I have not yet tried it with pypy. Will try it and compare the speed at some point when I have time.  
  
  ---
  
  ### Answer by username_2 on 2022-07-15. Score: 3
  
  I'm not sure any of these solutions below provide exactly what you're looking for, but I think enough functionality is there to assist you in your goal. Though the second option is very similar to the [Chess365 functionality](https://www.365chess.com/opening.php?m=4&n=74&ms=e4.e5.d4&ns=3.5.74) you reference.
  
  **Option 1: ChessGames.com General Search**  
  [ChessGames.com](https://www.chessgames.com/) allows searches by ECO code or opening. For example, [here are the results](https://www.chessgames.com/perl/chess.pl?yearcomp=exactly&year=2021&playercomp=either&pid=&player=&pid2=&player2=&movescomp=exactly&moves=&opening=C45&eco=&result=) for games in the [Scotch](https://en.wikipedia.org/wiki/Scotch_Game) (ECOs C45–45) restricted to the year 2021. You can further restrict games by result (White wins, Black wins, draw, or "no draw"). You can parse the results easily enough.
  
  **Option 2: ChessGames.com Opening Explorer**  
  ChessGames.com also has an opening explorer that will list around 6 practitioners of that opening ECO code (3 with the White pieces, and 3 with Black). For example, searching ECO code 65 ([Berlin Defense](https://en.wikipedia.org/wiki/Berlin_Defence_(chess)) is 65–67) gives the following.
  
  [![Results from search](https://i.sstatic.net/eTO3f.png)](https://i.sstatic.net/eTO3f.png)
  
  **Option 3: ChessTempo.com Opening Explorer**  
  [ChessTempo.com](https://chesstempo.com/) has an [opening explorer](https://old.chesstempo.com/game-database.html) with some added filters including specifying a rating range. Again, you'd have to parse the results, but it seems relevant.
  
  For example, I asked for all games with position after **1. e4 c5 2. Nc3 Nc6 3. f4** ([Grand Prix Attack](https://en.wikipedia.org/wiki/Sicilian_Defence#Grand_Prix_Attack)) with both players rated 2700+. It returns the following.
  
  [![Search results from ChessTempo](https://i.sstatic.net/64KFI.png)](https://i.sstatic.net/64KFI.png)
  
  > **Comments:**
  > **username_0**: Basically what I want is like your option 2, but with a longer list of players  
  
  ---
  
  ### Answer by username_4 on 2022-08-08. Score: 1
  
  You could use `pgn-extract -e3 pgn-file-name` to split the pgn file by ECO codes of games, e.g., you will get files C60.pgn to C99.pgn for Ruy Lopez. You can then combine C60.pgn to C99.pgn to get a single Ruy Lopez file. You may also be able to export from scid vs pc games in a range of ECO codes. You can then simply browse the file in scid vs pc. Or extract games of a specific player (again using pgn-extract) and you will see how many games are extracted. Otherwise, you can use a "simple" bash (e.g., grep/sort/wc commands)/awk/sed/perl/python script to get player frequencies in a pgn file. (Sorry, I cannot write such a script quickly, but similar scripts may be available already.)
  
  If you are more interested in a specific player, then extract first by player name and then get the statistics of their openings. (By the way, pgn-extract can add opening codes in a pgn file of they don't already exist.)
  
  Or in scid vs pc filter games containing a given position, say, the position after 1. e4 e5 2. Nf3 Nc6 3. Bb5, and browse the filtered list.
  
  
  ---
  
  