

PythonまたはRで以下のCSVファイルを読み込んで、クロス集計を行いたいのですが、うまくいきません。  
男性┗肉のようにクロス軸を二次元にする事は出来るのですが、一次元にする事が出来ません。

**CSVデータイメージ**  
[![SVデータイメージ](https://i.stack.imgur.com/7dTcM.png)](https://i.stack.imgur.com/7dTcM.png)

****クロス集計イメージ****  
[![クロス集計イメージ](https://i.stack.imgur.com/i0Gxd.png)](https://i.stack.imgur.com/i0Gxd.png)

ChatGPTで質問したところ以下の回答でしたが、主力イメージが意図した結果になりませんでした。  
ご教示いただけますと幸いです。宜しくお願いいたします。

**[![出力イメージ](https://i.stack.imgur.com/Ps4rR.png)](https://i.stack.imgur.com/Ps4rR.png)**

[code]

    # CSVファイルの読み込み
    df = pd.read_csv('ファイル名.csv')
    
    # クロス集計の実行
    cross_tab = pd.crosstab(index=[df['性別'], df['設問1']],
                            columns=df['設問2'], margins=True, margins_name='合計')
    
    # 列の順番を設定
    column_order = ['合計', 'TOYOTA', 'HONDA', 'BMW']
    cross_tab = cross_tab.reindex(columns=column_order)
    
    # 行の順番を設定
    index_order = [('全体', ''), ('男性', ''), ('女性', ''), ('肉', ''), ('魚', ''), ('合計', '')]
    cross_tab = cross_tab.reindex(index=index_order)
    
    # 結果の出力
    print(cross_tab)
    
[/code]


CC BY-SA 4.0
2023-03-22T04:00:55.283
94269
2023-03-28T04:36:46.470
2023-03-22T04:03:38.367
3060
57628
question
python r
PythonまたはRでクロス集計をしたい


性別と設問1を別個に集計して結合します。

[code]

    import pandas as pd
    
    # CSVファイルの読み込み
    df = pd.read_csv('data.csv')
    
    # クロス集計
    cross_tab = pd.concat([
        df.pivot_table(index='性別', columns='設問2', aggfunc='size', fill_value=0),
        df.pivot_table(index='設問1', columns='設問2', aggfunc='size', fill_value=0)])
    cross_tab['合計'] = cross_tab.sum(axis=1)
    cross_tab.loc['全体'] = cross_tab.sum()
    cross_tab.rename_axis('性別/設問1', inplace=True)
    
    # インデックスの順序を変更
    column_order = ['合計', 'TOYOTA', 'HONDA', 'BMW']
    index_order = ['全体', '男性', '女性', '肉', '魚']
    cross_tab = cross_tab.reindex(index=index_order, columns=column_order)
    
    # 結果の出力
    print(cross_tab)
    
    # 設問2       合計  TOYOTA  HONDA  BMW
    # 性別/設問1                          
    # 全体           8       4      2    2
    # 男性           2       1      1    0
    # 女性           2       1      0    1
    # 肉             2       1      1    0
    # 魚             2       1      0    1
    
[/code]


CC BY-SA 4.0
2023-03-22T05:46:11.170
94270
2023-03-22T05:46:11.170
47127
94269
answer


既に解決済みですが，御参考として `R` の記述例（`tidyverse` パッケージを使用）を示します。  
手順としては，`count()` と `pivot_wider()`
を使って設問2の全体集計と2個のクロス集計（性別\設問2，設問1\設問2）を作り，これらを縦に結合してから「合計」列を追加しました。また，最初に `df`
の各列を `factor()` で変換しているのは `levels` で表示順を設定するためです。なお，実行環境は「macOS 13.2.1(M1), R
4.2.3, tidyverse 2.0.0」です。

[code]

    library(tidyverse)
    
    df <- read_csv('data.csv', show_col_types=FALSE)
    
    df <- df |>
        mutate(性別=factor(性別, levels=c('男性', '女性')),
               設問1=factor(設問1, levels=c('肉', '魚')),
               設問2=factor(設問2, levels=c('TOYOTA', 'HONDA', 'BMW')))
    
    df1 <- count(df, 設問2) |>
        pivot_wider(names_from=設問2, values_from=n) |>
        mutate(区分=c('全体'), .before=1)
    
    df2 <- count(df, 性別, 設問2) |>
        pivot_wider(names_from=設問2, values_from=n, values_fill=0) |>
        rename(区分=性別)
    
    df3 <- count(df, 設問1, 設問2) |>
        pivot_wider(names_from=設問2, values_from=n, values_fill=0) |>
        rename(区分=設問1)
    
    df4 <- rbind(df1, df2, df3) |>
        rowwise() |>
        mutate(合計=sum(TOYOTA, HONDA, BMW), .after=1)
    
    print(as.data.frame(df4))
    
[/code]

[code]

      区分 合計 TOYOTA HONDA BMW
    1 全体    4      2     1   1
    2 男性    2      1     1   0
    3 女性    2      1     0   1
    4   肉    2      1     1   0
    5   魚    2      1     0   1
    
[/code]


CC BY-SA 4.0
2023-03-28T04:36:46.470
94351
2023-03-28T04:36:46.470
54588
94269
answer