色々と調べてみたはいいものの、書き方がつかめずどうしても固まってしまいます。お力添えをよろしくお願いいたします。  
各染色体について父由来か母由来どちらの染色体を子孫に渡すかによってどんな能力のパターンがある得るかのシミュレーションです。

chr_effect.txtのようなデータファイルがあります。  
animal、pnt、chr1...chr29の31列あり、各animalにつきpntが1と2あります。便宜上最初の5つのanimal（10行）しか表示していませんが、実際には約5,000つのanimal、すなわち10,000行データがあります。

別にchr_pnt.txtのようなファイルがあります。  
便宜上最初の10行しか表示していませんが、実際には100,000行×29列（chr1...chr29）のデータで、pntを示す1もしくは2が入っています。

やりたいことは、以下のような処理です。

  1. chr_pntの各要素（chrとpntで一意的に定まる）に対応するchr_effectの値を抽出する。
  2. 取り出したchr_effectの値からchr1...chr29までの和を算出する。
  3. 算出した和（100,000個）の平均値と標準偏差を返す。
  4. 以上の処理をすべてのanimalごとに行い、ファイル出力する。

出力したいファイルのイメージはsolutions.txtです。  
説明がわかりにくくて申し訳ないです。

わたし個人では、恥ずかしながら以下のようにデータ読み込みの段階で思考が固まってしまいます。

```

    import pandas as pd
    
    chr_effect = pd.read_table('chr_effect.txt', delim_whitespace=True)
    chr_pnt = pd.read_table('chr_pnt.txt', delim_whitespace=True)
    
```

**chr_effect.txt**

```

    animal  pnt chr1    chr2    chr3    chr4    chr5    chr6    chr7    chr8    chr9    chr10   chr11   chr12   chr13   chr14   chr15   chr16   chr17   chr18   chr19   chr20   chr21   chr22   chr23   chr24   chr25   chr26   chr27   chr28   chr29
    27790   1   -3.249619881    1.776331581 -2.24113552 -4.817298276    -5.48548554 -1.759651526    5.334048371 3.891744788 1.884854677 -3.242535628    3.756604968 2.986742453 0.612356541 -2.86922751 4.352907409 0.90651085  -0.412862385    0.296373936 -5.889000773    -0.68745163 0.298499644 0.814954378 -0.095186506    0.865718907 2.540816382 5.789061632 -0.559834391    -2.53661836 0.751069038
    27790   2   -0.390512283    0.3496771   -2.139579662    -4.59481831 -0.776924186    -0.35638789 -0.526063862    -0.477037798    -1.569054067    -2.90589106 -1.465912498    -3.364848089    0.975073498 -9.574933303    -2.323818571    -2.219380737    -3.775384093    -0.309000541    -0.003886077    1.91834523  -0.124754068    2.23336583  -2.7314078  -1.352587759    -2.121087552    -0.59768476 0.519127176 5.32087313  1.659182504
    75952   1   1.860075236 -1.952826593    7.941593806 6.971151872 -5.39318137 24.5906086  -0.627978002    1.558862775 -2.044366214    1.593249157 -1.53647959 -5.210752328    3.478248395 -5.889005176    -0.485182934    1.525452838 -5.212397443    1.330459383 3.158410718 -1.316064027    3.041514078 2.484066153 -1.601287478    4.598523036 1.176341264 -0.732658875    -1.546846435    -0.241240957    -2.703045534
    75952   2   0.07320026  -1.193285236    3.664270318 -1.198182299    -3.285812454    -7.21470412 1.759143544 7.648100385 1.693592132 0.946791605 -2.87792026 -2.67183088 -1.945447857    2.474190902 -2.621106236    -2.764357816    -2.279304115    0.00797417  0.663827378 1.58174674  1.271269494 1.272317695 1.142039742 0.076808881 -0.46131242 3.365393607 -1.174178405    -2.626477213    -1.37721366
    90414   1   1.739067807 2.705188308 -1.245923538    -0.002399875    -2.599279152    -0.154139815    0.303458033 2.786962772 -2.988691596    0.725134479 -1.551469947    1.406454822 1.488023864 0.978901455 1.780002113 -5.183237296    -1.602299904    0.057587453 4.119123527 -3.148129947    -0.699950319    -0.354722639    0.366632135 4.998152571 1.543905898 3.172006996 -5.345136372    -0.056620664    2.422692998
    90414   2   -2.519037307    -0.926182651    0.66829595  0.083873692 -3.127323408    -7.296881507    -0.797579   -1.692284026    0.446947886 -2.593041865    -4.321641322    1.195738671 -1.478727635    4.047270398 2.312901751 -5.3839035  -0.904768118    -3.425975528    -0.418056083    0.648341358 -0.674819627    -1.525995063    0.219910922 0.381569648 -1.513227344    2.566777598 -2.742408197    2.510699832 -1.25012918
    90470   1   1.451065566 7.687896532 1.118122984 0.217045435 -4.390935698    -2.358229388    -8.346397709    2.006546339 5.738527934 -3.025387626    -4.028971005    1.712205845 3.627846534 6.986557249 0.963232976 -6.304871835    0.176607468 0.800108489 -0.063414724    6.655480908 -3.68568447 -1.681859217    0.952996904 -3.51742161 -1.585046358    -0.40142409 -1.222321719    5.864682736 0.77443274
    90470   2   -3.236474166    -0.828191866    0.864194126 -2.386854158    -5.98932058 -4.859134618    -1.443351926    0.280750195 7.801439742 -4.921804746    1.155552973 1.624703212 -0.895162234    -5.903743854    0.901627188 0.187514121 -2.314349528    -5.426454814    3.349431154 6.005233669 -1.902131074    -1.325578071    0.787564088 -0.522419842    -1.345004348    1.169492376 1.537055754 6.767023934 -3.057591512
    102853  1   0.01378943  10.9234678  1.456693154 0.034962635 -5.202454665    -1.662830588    -4.066262419    10.26374255 6.980704894 -1.44364735 -10.15811404    -4.508814067    4.862243682 7.606665536 -0.010935424    -1.73585101 -0.57417706 -1.087272208    4.78751793  7.514152847 -1.479511504    -1.681859217    0.472674332 -0.056568908    -3.122885588    4.59333307  2.501062924 2.730274228 0.727288217
    102853  2   1.398403246 1.072480483 -8.505226254    2.64111658  -2.297556361    -1.40125181 -0.318009921    13.65483956 -0.776215002    1.719216586 -3.03228246 -5.971878011    -0.004130784    2.885798136 2.377923162 0.57592465  -3.414375536    -2.701702732    3.752473244 0.186915701 3.673363686 -2.915896525    0.89251478  5.26937868  -1.79715952 2.484896944 -1.231909699    2.871125798 1.623539915
    
```

**chr_pnt.txt**

```

    chr1    chr2    chr3    chr4    chr5    chr6    chr7    chr8    chr9    chr10   chr11   chr12   chr13   chr14   chr15   chr16   chr17   chr18   chr19   chr20   chr21   chr22   chr23   chr24   chr25   chr26   chr27   chr28   chr29
    2   2   1   1   2   2   2   1   1   1   1   1   1   2   1   2   2   2   2   1   2   1   2   1   2   2   1   1   2
    1   2   2   1   2   1   2   1   1   1   1   1   1   2   2   2   1   1   2   1   1   1   1   2   2   2   2   1   1
    1   1   2   2   1   1   1   2   2   2   2   1   1   2   2   1   1   1   1   1   2   2   2   1   1   1   1   1   1
    2   1   2   2   1   2   2   1   2   1   1   2   1   2   2   1   2   2   2   1   2   2   1   1   2   1   1   2   2
    1   2   2   1   1   2   2   1   2   1   1   1   1   2   1   1   2   1   1   2   2   1   1   2   2   2   1   2   1
    2   1   2   2   2   2   2   1   1   1   1   1   1   1   2   1   1   1   2   2   1   1   2   2   2   1   1   1   1
    2   2   1   2   1   1   1   1   2   1   1   1   2   2   2   1   1   2   1   1   2   2   1   2   2   2   1   1   2
    1   2   1   2   1   1   1   2   2   2   2   1   2   2   1   1   2   2   1   1   2   2   1   2   1   1   1   2   1
    2   2   2   2   1   1   1   2   1   2   2   2   1   1   2   2   2   1   2   1   1   1   2   1   1   2   1   2   1
    1   1   1   1   1   1   1   2   1   1   2   2   1   2   1   2   1   2   1   2   1   1   2   1   1   2   1   1   1
    
```

**solutions.txt**

```

    animal  average std
    27790   -13.80468698    10.76483559
    75952   11.4056846  18.58066141
    90414   -10.91855174    8.140109257
    90470   -3.89969823 11.36792823
    102853  20.69108446 11.8625067
    
```
CC BY-SA 4.0
2022-12-07T05:53:16.207
92618
2022-12-13T08:01:25.867
2022-12-13T08:01:25.867
54671
54671
question
python pandas bioinformatics
python pandasによるデータ処理について
手順通りに処理を行うとすれば以下の通り(質問に記載されている `solutions.txt` の内容と処理結果が異なっていますけれども)。

```

    import pandas as pd
    
    chr_effect = pd.read_table('chr_effect.txt', delim_whitespace=True)
    chr_pnt = pd.read_table('chr_pnt.txt', delim_whitespace=True)
    
    def mapping(animal):
        a = animal.set_index('pnt')
        return chr_pnt.apply(lambda c: c.apply(lambda x: a.loc[x, c.name]))\
                      .sum(axis=1).agg(average='mean', std='std')
    
    chrx = chr_effect.groupby('animal').apply(mapping)
    print(chrx)
    
```

animal | average | std  
---|---|---  
27790 | -18.5713 | 7.74195  
75952 | 15.9058 | 19.3923  
90414 | -8.52192 | 8.27256  
90470 | -7.5583 | 11.9928  
102853 | 20.3525 | 8.98747
CC BY-SA 4.0
2022-12-07T20:01:47.870
92627
2022-12-07T20:01:47.870
47127
92618
answer
> 色々と調べてみたはいいものの、書き方がつかめず

以下は総和の算出の手順です。あとは同じようにできるはず

* * *

animal ＆ pnt ごとに管理されているので  
① まず chr_pnt を pnt ごとにそれぞれ集計 (ch29 まで 29項目)

```

    print((dfpnt == 1).sum(axis=0).to_list())   # pnt == 1 の場合
    # [5, 4, 4, 4, 7, 6, 5, 6, 5, 7, 6, 7, 8, 2, 4, 6, 5, 5, 5, 7, 4, 6, 5, 5, 4, 4, 9, 6, 7]
    
```

② chr_effect を pnt ごとに抽出して

```

    display(dfeff[dfeff.pnt == 1])
    
```

animal | pnt | chr1 | chr2 | chr3 | chr4 | chr5 | chr6 | chr7 | chr8 | chr9 |
chr10 | chr11 | chr12 | chr13 | chr14 | chr15 | chr16 | chr17 | chr18 | chr19
| chr20 | chr21 | chr22 | chr23 | chr24 | chr25 | chr26 | chr27 | chr28 |
chr29  
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---  
27790 | 1 | -3.24962 | 1.77633 | -2.24114 | -4.8173 | -5.48549 | -1.75965 |
5.33405 | 3.89174 | 1.88485 | -3.24254 | 3.7566 | 2.98674 | 0.612357 |
-2.86923 | 4.35291 | 0.906511 | -0.412862 | 0.296374 | -5.889 | -0.687452 |
0.2985 | 0.814954 | -0.0951865 | 0.865719 | 2.54082 | 5.78906 | -0.559834 |
-2.53662 | 0.751069  
75952 | 1 | 1.86008 | -1.95283 | 7.94159 | 6.97115 | -5.39318 | 24.5906 |
-0.627978 | 1.55886 | -2.04437 | 1.59325 | -1.53648 | -5.21075 | 3.47825 |
-5.88901 | -0.485183 | 1.52545 | -5.2124 | 1.33046 | 3.15841 | -1.31606 |
3.04151 | 2.48407 | -1.60129 | 4.59852 | 1.17634 | -0.732659 | -1.54685 |
-0.241241 | -2.70305  
90414 | 1 | 1.73907 | 2.70519 | -1.24592 | -0.00239988 | -2.59928 | -0.15414 |
0.303458 | 2.78696 | -2.98869 | 0.725134 | -1.55147 | 1.40645 | 1.48802 |
0.978901 | 1.78 | -5.18324 | -1.6023 | 0.0575875 | 4.11912 | -3.14813 |
-0.69995 | -0.354723 | 0.366632 | 4.99815 | 1.54391 | 3.17201 | -5.34514 |
-0.0566207 | 2.42269  
90470 | 1 | 1.45107 | 7.6879 | 1.11812 | 0.217045 | -4.39094 | -2.35823 |
-8.3464 | 2.00655 | 5.73853 | -3.02539 | -4.02897 | 1.71221 | 3.62785 |
6.98656 | 0.963233 | -6.30487 | 0.176607 | 0.800108 | -0.0634147 | 6.65548 |
-3.68568 | -1.68186 | 0.952997 | -3.51742 | -1.58505 | -0.401424 | -1.22232 |
5.86468 | 0.774433  
102853 | 1 | 0.0137894 | 10.9235 | 1.45669 | 0.0349626 | -5.20245 | -1.66283 |
-4.06626 | 10.2637 | 6.9807 | -1.44365 | -10.1581 | -4.50881 | 4.86224 |
7.60667 | -0.0109354 | -1.73585 | -0.574177 | -1.08727 | 4.78752 | 7.51415 |
-1.47951 | -1.68186 | 0.472674 | -0.0565689 | -3.12289 | 4.59333 | 2.50106 |
2.73027 | 0.727288  
  
③ あとは乗算

```

    df1,df2 = (dfeff抽出分 * dfpnt集計分 for p in (1,2))
    dfsum = df1 + df2
    
    # pnt1, pnt2 を分けることなく加算する場合
    dfsum = sum(dfeff抽出分 * dfpnt集計分 for p in (1,2))
    
```

以上をまとめると

```

    import pandas as pd
    dfeff = pd.read_csv(chr_effect, sep='\s+', index_col='animal')
    dfpnt = pd.read_csv(chr_pnt, sep='\s+')
    
    dfsum = sum(dfeff.loc[dfeff.pnt == p, 'chr1':'chr29']
                     .mul((dfpnt == p).sum(axis='index'), axis='columns')
                                                          for p in (1,2))
    
    display(dfsum.sum(axis='columns'))
    # animal
    # 27790    -185.712504
    # 75952     159.058371
    # 90414     -85.219206
    # 90470     -75.583044
    # 102853    203.524688
    # dtype: float64
    
```

* * *

#### 追記

chr_pnt 件数での平均の場合

```

    print(dfpnt.shape)   # (10, 29)
    len(dfpnt)   # 10
    
    display(dfsum.sum(axis='columns') / len(dfpnt))
    # animal
    # 27790    -18.571250
    # 75952     15.905837
    # 90414     -8.521921
    # 90470     -7.558304
    # 102853    20.352469
    # dtype: float64
    
```
CC BY-SA 4.0
2022-12-07T22:41:57.523
92629
2022-12-09T02:43:09.007
2022-12-09T02:43:09.007
43025
43025
92618
answer
「 pandas によるデータ処理」とは言えないかもしれないので御参考です。なお，既に回答された方と標準偏差の値が異なるのは pandas と numpy
でデフォルトの計算式が異なるためです。一致させるには`np.std(sum_list)` を `np.std(sum_list, ddof=1)`
としてください。とはいえ「データ数: 100,000 」では差はほとんどなくなります。

```

    import pandas as pd
    import numpy as np
    
    chr_effect = pd.read_table('chr_effect.txt', delim_whitespace=True)
    chr_pnt = pd.read_table('chr_pnt.txt', delim_whitespace=True)
    
    print('  animal    average        std')
    for i in range(0, len(chr_effect.index), 2):
        anml = chr_effect.iloc[i, 0]
        p1 = chr_effect.iloc[i, 2:]
        p2 = chr_effect.iloc[i+1, 2:]
        sum_list = []
        for cp in chr_pnt.to_numpy():
            sum_list.append(p1[cp == 1].sum() + p2[cp == 2].sum())
        print(f'{anml:8d} {np.mean(sum_list):10.4f} {np.std(sum_list):10.4f}')
    
```

```

      animal    average        std
       27790   -18.5713     7.3447
       75952    15.9058    18.3972
       90414    -8.5219     7.8480
       90470    -7.5583    11.3774
      102853    20.3525     8.5263
    
```

（追記）  
chr_pnt.txt を 100,000行に増やして処理時間を計測すると，私の環境（MacOS13(M1), Python 3.10.8）で
30秒ほどでした。animal 数 5,000では単純計算で
500分になります。そこで，下記のように内積計算に変更したところ処理時間は約20分の1（1.6秒）になりました。

```

        # p1 = chr_effect.iloc[i, 2:]
        # p2 = chr_effect.iloc[i+1, 2:]
        p1 = chr_effect.iloc[i, 2:].to_numpy()
        p2 = chr_effect.iloc[i+1, 2:].to_numpy()
    
            # sum_list.append(p1[cp == 1].sum() + p2[cp == 2].sum())
            sum_list.append(p1 @ (2 - cp) + p2 @ (cp - 1))
    
```
CC BY-SA 4.0
2022-12-08T17:09:55.073
92649
2022-12-09T05:48:03.113
2022-12-09T05:48:03.113
54588
54588
92618
answer