Todas las combinaciones posibles de columnas en el marco de datos-pandas/python
combinations (4)
Estoy tratando de tomar un marco de datos y crear otro, con todas las combinaciones posibles de las columnas y la diferencia entre los valores correspondientes, es decir, en la columna AB de 11 ap debe ser (BA) = 0, etc.
por ejemplo, empezando por
Dt A B C D
11-apr 1 1 1 1
10-apr 2 3 1 2
¿Cómo obtengo un nuevo marco que se ve así:
He encontrado la publicación a continuación, pero no he podido transponer esto para trabajar en columnas.
Agregue todas las combinaciones de pares de fila de datos con pandas
Asegúrate de que tu índice sea Dt
df = df.set_index(''Dt'')
Usando numpy
s np.tril_indices
y slicing Vea a continuación para la explicación de np.triu_indices
v = df.values
i, j = np.tril_indices(len(df.columns), -1)
Podemos crear un pd.MultiIndex
para las columnas. Esto lo hace más generalizable para los nombres de columna que son más largos que un carácter.
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
Pero también podemos hacer
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
explicado
Esta es una función numpy
que devuelve dos matrices que, cuando se utilizan juntas, proporcionan las ubicaciones de un triángulo inferior de una matriz cuadrada. Esto es útil cuando se hacen manipulaciones de todas las combinaciones de cosas, ya que este triángulo inferior representa todas las combinaciones de un eje de una matriz con la otra.
Considere el marco de datos d
para ilustración
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
Los índices triangulares, cuando se ven como pares de coordenadas, se ven así
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)]
Puedo manipular valores d
s con i
y j
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
Y puedes ver que se enfoca solo en ese triángulo inferior
prueba de tiempo ingenua
Puedes usar:
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
Itertools
módulo Itertools
debería ayudarlo a crear las combinaciones / permutaciones requeridas.
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
itertools.combinations
lo ayudará a:
import itertools
pd.DataFrame({''{}{}''.format(a, b): df[a] - df[b] for a, b in itertools.combinations(df.columns, 2)})
Lo que resulta en:
AB AC AD BC BD CD
Dt
11-apr 0 0 0 0 0 0
10-apr -1 1 0 2 1 -1