Tengo 98 muestras / marcos de datos de los cuales he remodelado en un marco de datos mediante concatenación.

El marco de datos se ha sometido a una clasificación y un filtrado exhaustivos para identificar el locus y compararlo con todo su grupo.

Ejemplo.

data = {"Overall_Sample":["Sample1", "Sample1", "Sample1", "Sample1", "Sample1", "Sample1", "Sample1", "Sample1", "Sample2", "Sample2", "Sample2", "Sample2", "Sample2", "Sample2", "Sample2"], "Sub_Sample":["Sample1_a", "Sample1_a", "Sample1_a", "Sample1_a", "Sample1_b", "Sample1_b", "Sample1_b", "Sample1_b", "Sample2_a", "Sample2_a", "Sample2_a", "Sample2_b", "Sample2_b", "Sample2_b", "Sample2_b"], "Panel":["a", "a", "a", "a", "b", "b", "b", "b", "a", "a", "a", "b", "b", "b", "b"], "Identified_Locus":["Locus1", "Locus2", "Locus3", "Locus4", "Locus2", "Locus3", "Locus4", "Locus5", "Locus3", "Locus5", "Locus6", "Locus1", "Locus3", "Locus5", "Locus6"]}

df.DataFrame(data)

Deseo encontrar el Locus de intersección por sampleName entre el panel ay b.

Resultado deseado.

Sample1 
Intersecting: Locus2, Locus3, Locus4
Panel a unique: Locus1
Panel b unique: Locus5

Sample2
Intersecting: Locus3, Locus5, Locus6
Panel a unique: None
Panel b unique: Locus1

with 3 different lists, 
intersection = (3,3)
Panel a unique = (1, 0)
Panel b unique = (1, 1)

El objetivo es hacer un gráfico de barras porcentual al final.

He tenido éxito manualmente para dividir el marco de datos y recuperar la salida deseada. Pero me gustaría evitar dividir el marco de datos: ¿es posible mantenerlo en el marco de datos principal y aún así recuperar la salida deseada?

El código que utilicé para identificar manualmente los que se cruzan y los únicos.

grouped = df.groupby(df.Sub_Sample)
sample1_a = grouped.get_group("Sample1_a")
sample1_b = grouped.get_group("Sample1_b")

sample1a_locus = sample1_a["Locus"].tolist()
sample1b_locus = sample1_b["Locus"].tolist()

sample1a_set = set(sample1a_locus)
sample1b_set = set(sample1a_locus)

Overlap_locus = sample1a_set.intersection(sample1b_set)
Panel_a_unique = sample1a_set.symmetric_difference(sample1b_set)
Panel_b_unique = sample1b_set.symmetric_difference(sample1a_set)

Overlapping_genes.append(len(Overlap_locus))
Panela_unique.append(len(Panel_a_unique))
Panelb_unique.append(len(Panel_b_unique))
3
LVES0067 25 feb. 2021 a las 14:18

2 respuestas

La mejor respuesta

Creo que tu código no está mal. Aquí hay un enfoque un poco más conciso que se escala también a conjuntos de datos más grandes.

Puede obtener los valores únicos para Identified_Locus por submuestra con

locus_per_sub_sample = df.groupby(['Overall_Sample', 'Panel'])['Identified_Locus'].apply(lambda grp: set(grp))

A continuación, puede realizar operaciones de configuración en las diferentes muestras con bastante facilidad. Por ejemplo, para obtener la cantidad de elementos compartidos entre las submuestras para Sample1, puede hacer lo siguiente:

len(set.intersection(*locus_per_sub_sample.loc[pd.IndexSlice['Sample1', :]]))

De manera similar, para los elementos únicos de las submuestras Sample1_a y Sample1_b:

symmetric_difference1 = set.symmetric_difference(*locus_per_sub_sample.loc[pd.IndexSlice['Sample1', :]])

Para obtener la diferencia simétrica para cada submuestra

locus_per_sub_sample.loc[pd.IndexSlice['Sample1', :]].apply(
     lambda r: r.intersection(symmetric_difference1))

Que te da

Overall_Sample  Panel
Sample1         a        {Locus1}
                b        {Locus5}
Name: Identified_Locus, dtype: object
0
gofvonx 25 feb. 2021 a las 15:32

Fui con la creación de un bucle for para agregar una lista, respectivamente. La lista será necesaria para crear un gráfico de barras de porcentaje para una fácil visualización en una presentación.

names = df.Overall_Sample.unique()
Overlapping_locus = []
Sample1_unique = [] 
Sample2_unique = []
for i in names:
    Overlapping_Locus.append(len(set.intersection(*locus_per_sample.loc[pd.IndexSlice[i]])))
    Sample1_unique.append(len(locus_per_sample.loc[pd.IndexSlice[[i], :]].apply(lambda u: u.intersection(set.symmetric_difference(*locus_per_sample.loc[pd.IndexSlice[[i], :]])))[0]))
    Sample2_unique.append(len(locus_per_sample.loc[pd.IndexSlice[[i], :]].apply(lambda u: u.intersection(set.symmetric_difference(*locus_per_sample.loc[pd.IndexSlice[[i], :]])))[1]))
0
LVES0067 12 mar. 2021 a las 13:47