web-dev-qa-db-ja.com

reshape a pandas dataframe

このようなデータフレームを想定します:

df = pd.DataFrame([[1,2,3,4],[5,6,7,8],[9,10,11,12]], columns = ['A', 'B', 'A1', 'B1'])

enter image description here

次のようなデータフレームが必要です。

enter image description here

動作しないもの:

new_rows = int(df.shape[1]/2) * df.shape[0]
new_cols = 2
df.values.reshape(new_rows, new_cols, order='F')

もちろん、データをループして新しいリストのリストを作成することもできますが、もっと良い方法が必要です。何か案は ?

10
Moritz

pd.wide_to_long関数は、このような状況にほぼ正確に対応するように構築されており、同じ変数プレフィックスの多くが異なる数字のサフィックスで終わっています。ここでの唯一の違いは、変数の最初のセットにはサフィックスがないため、最初に列の名前を変更する必要があることです。

pd.wide_to_longの唯一の問題は、iとは異なり、識別変数meltを持たなければならないことです。 reset_indexは、この一意に識別する列を作成するために使用され、後で削除されます。これは将来修正される可能性があると思います。

df1 = df.rename(columns={'A':'A1', 'B':'B1', 'A1':'A2', 'B1':'B2'}).reset_index()
pd.wide_to_long(df1, stubnames=['A', 'B'], i='index', j='id')\
  .reset_index()[['A', 'B', 'id']]

    A   B id
0   1   2  1
1   5   6  1
2   9  10  1
3   3   4  2
4   7   8  2
5  11  12  2
5
Ted Petrou

lreshapeid を使用できます numpy.repeat

a = [col for col in df.columns if 'A' in col]
b = [col for col in df.columns if 'B' in col]
df1 = pd.lreshape(df, {'A' : a, 'B' : b})

df1['id'] = np.repeat(np.arange(len(df.columns) // 2), len (df.index))  + 1
print (df1)
    A   B  id
0   1   2   1
1   5   6   1
2   9  10   1
3   3   4   2
4   7   8   2
5  11  12   2

編集:

lreshape は現在文書化されていませんが、削除される可能性があります( with pd.wide_to_long too )。

考えられる解決策は、3つの関数すべてを1つにマージすることです。おそらくmeltですが、現在は実装されていません。たぶんパンダのいくつかの新しいバージョンで。その後、私の答えが更新されます。

8
jezrael

これを3つのステップで解決しました。

  1. 初期データフレームdfに追加するデータのみを保持する新しいデータフレーム_df2_を作成します。
  2. 以下に追加される(および_df2_を作成するために使用された)データをdfから削除します。
  3. _df2_をdfに追加します。

そのようです:

_# step 1: create new dataframe
df2 = df[['A1', 'B1']]
df2.columns = ['A', 'B']

# step 2: delete that data from original
df = df.drop(["A1", "B1"], 1)

# step 3: append
df = df.append(df2, ignore_index=True)
_

df.append()を実行するときに_ignore_index=True_を指定する必要があることに注意してください。これにより、新しい列が古いインデックスを保持するのではなく、インデックスに追加されます。

最終結果は、元のデータフレームになり、必要に応じてデータが再配置されます。

_In [16]: df
Out[16]:
    A   B
0   1   2
1   5   6
2   9  10
3   3   4
4   7   8
5  11  12
_
2
mprat

pd.concat()を次のように使用します。

#Split into separate tables
df_1 = df[['A', 'B']]
df_2 = df[['A1', 'B1']]
df_2.columns = ['A', 'B'] # Make column names line up

# Add the ID column
df_1 = df_1.assign(id=1)
df_2 = df_2.assign(id=2)

# Concatenate
pd.concat([df_1, df_2])
1
Matthew