1つのデータフレームを取得して別のデータフレームを作成しようとしています。列のすべての可能な組み合わせと、対応する値の差があります。つまり、11-apr列ABでは(B-A)= 0などになります。
例:
Dt A B C D
11-apr 1 1 1 1
10-apr 2 3 1 2
次のような新しいフレームを取得するにはどうすればよいですか。
以下の投稿に出くわしましたが、これを列に置き換えることができませんでした。
次を使用できます。
from itertools import combinations
df = df.set_index('Dt')
cc = list(combinations(df.columns,2))
df = pd.concat([df[c[1]].sub(df[c[0]]) for c in cc], axis=1, keys=cc)
df.columns = df.columns.map(''.join)
print (df)
AB AC AD BC BD CD
Dt
11-apr 0 0 0 0 0 0
10-apr 1 -1 0 -2 -1 1
インデックスがDt
であることを確認してください
df = df.set_index('Dt')
numpy
s np.tril_indices
の使用とスライスnp.triu_indices
の説明については、以下を参照してください。
v = df.values
i, j = np.tril_indices(len(df.columns), -1)
列にpd.MultiIndex
を作成できます。これにより、1文字より長い列名に対してより一般化できるようになります。
pd.DataFrame(
v[:, i] - v[:, j],
df.index,
[df.columns[j], df.columns[i]]
)
A B A B C
B C C D D D
Dt
11-apr 0 0 0 0 0 0
10-apr 1 -1 -2 0 -1 1
しかし、私たちもできます
pd.DataFrame(
v[:, i] - v[:, j],
df.index,
df.columns[j] + df.columns[i]
)
AB AC BC AD BD CD
Dt
11-apr 0 0 0 0 0 0
10-apr 1 -1 -2 0 -1 1
np.tril_indices
説明
これはnumpy
関数であり、一緒に使用すると、正方行列の下三角形の位置を提供する2つの配列を返します。この下の三角形は、行列の1つの軸と他の軸のすべての組み合わせを表すため、これは、すべての組み合わせを操作するときに便利です。
説明のためにデータフレームd
を検討してください
d = pd.DataFrame(np.array(list('abcdefghijklmnopqrstuvwxy')).reshape(-1, 5))
d
0 1 2 3 4
0 a b c d e
1 f g h i j
2 k l m n o
3 p q r s t
4 u v w x y
三角形のインデックスは、座標ペアのように見ると、次のようになります。
i, j = np.tril_indices(5, -1)
list(Zip(i, j))
[(1, 0),
(2, 0),
(2, 1),
(3, 0),
(3, 1),
(3, 2),
(4, 0),
(4, 1),
(4, 2),
(4, 3)]
d
とi
を使用してj
sの値を操作できます
d.values[i, j] = 'z'
d
0 1 2 3 4
0 a b c d e
1 z g h i j
2 z z m n o
3 z z z s t
4 z z z z y
そして、あなたはそれがちょうどその下の三角形をターゲットにしているのを見ることができます
ナイーブタイムテスト
itertools.combinations
が手伝う:
import itertools
pd.DataFrame({'{}{}'.format(a, b): df[a] - df[b] for a, b in itertools.combinations(df.columns, 2)})
その結果:
AB AC AD BC BD CD
Dt
11-apr 0 0 0 0 0 0
10-apr -1 1 0 2 1 -1
Itertools
モジュールは、必要な組み合わせ/順列を作成するのに役立ちます。
from itertools import combinations
# Creating a new pd.DataFrame
new_df = pd.DataFrame(index=df.index)
# list of columns
columns = df.columns
# Create all combinations of length 2 . eg. AB, BC, etc.
for combination in combinations(columns, 2):
combination_string = "".join(combination)
new_df[combination_string] = df[combination[1]]-df[combination[0]]
print new_df
AB AC AD BC BD CD
Dt
11-apr 0 0 0 0 0 0
10-apr 1 -1 0 -2 -1 1