2017-03-15 4 views
0

Ich möchte zwei Zeilen und zwei Spalten gleichzeitig in einem Pandas-Dataframe lesen und dann bedingungsabhängig zip vs. product der Strings zwischen zwei Zeilen/Spalten-Matrix von pandas Dataframe anwenden.Wie liest man zwei Zeilen und zwei Spalten eines Pandas-Datenrahmens gleichzeitig und wendet Bedingungen auf diese Zeilen-/Spaltenwerte an?

import pandas as pd 
import itertools as it 
from itertools import product 

cond_mcve = pd.read_csv('condition01.mcve.txt', sep='\t') 

    alfa alfa_index beta beta_index delta delta_index 
0 a,b   23 c,d   36 a,c   32 
1 a,c   23 b,e   37 c,d   32 
2 g,h   28 d,f   37 e,g   32 
3 a,b   28 c,d   39 a,c   34 
4 c,e   28 b,g   39 d,k   34 
  • Hier alfa, beta und delta sind Werte, Strings und sie haben ihre eigene entsprechende Indizes.

  • Ich möchte die zip von zwei benachbarten Strings (nach Zeilen) erstellen, wenn sie die gleichen Indexwerte haben. Also, für die ersten zwei Zeilen für alfa column sollte die Ausgabe aa,cb sein, da die alfa_index für beide Zeilen 23 ist.

  • Aber für die 2. und 3. Zeile von alfa Spalte die beiden Indizes Wert unterscheiden (23 und 28), so sollte die Ausgabe ein Produkt der Strings sein, dh Ausgabe: ga, gc, ha, hc

Dies ist, was ich geistig zu tun do gedacht haben: Und ich hoffe, dass ich sehr deutlich das Problem bin zu erklären.

# write a function 
def some_function(): 
    read_two columns at once (based on prefix similarity) 

    then: 
    if two integer_index are same: 
     zip(of strings belonging to that index) 

    if two integer index are different: 
     product(of strings belonging to that index) 

# take this function and apply it to pandas dataframe: 
cond_mcve_updated = cond_mcve+cond_mcve.shift(1).dropna(how='all').applymap(some_function) 

Hier shift in der Lage, zwei Linien zu einem Zeitpunkt zu lesen, so mein Problem zwei Reihen auf einmal zu lesen ist gelöst. Aber , ich habe andere Probleme beim Lesen zwei Spalten und Umsetzung der Bedingung:

  • Lese zweispaltigen auf einmal in Pandas Datenrahmen (basierend auf Präfix Ähnlichkeit).
  • diese Spalten Trennindexwerten vergleichen (integer)
  • anwenden zip vs. Produkt basierend auf der Bedingung

Die erwartete Endausgabe wird:

alfa   alfa_index beta    beta_index delta delta_index 
1 aa,cb   23   bc,bd,ec,ed  37   ca,dc   32 
2 ga,gc,ha,hc 28   db,fe   37   ec,gd   32 
same for other line..... 

# the first index(i.e 0 is lost) but that's ok. I can work it out using `head/tail` method in pandas. 

Antwort

1

Hier ist ein Weg zu das Ergebnis erreichen. Diese Funktion verwendet shift, concat und apply, um die Daten in eine Funktion zu übertragen, die die Prod/Sum-Funktion basierend auf übereinstimmenden _index Werten ausführen kann.

Code:

import itertools as it 

def crazy_prod_sum_thing(frame): 
    # get the labels which do not end with _index 
    labels = [(l, l + '_index') 
       for l in frame.columns.values if not l.endswith('_index')] 

    def func(row): 
     # get row n and row n-1 
     front = row[:len(row) >> 1] 
     back = row[len(row) >> 1:] 

     # loop through the labels 
     results = [] 
     for l, i in labels: 
      x = front[l].split(',') 
      y = back[l].split(',') 
      if front[i] == back[i]: 
       results.append(x[0] + y[0] + ',' + x[1] + x[1]) 
      else: 
       results.append(
        ','.join([x1 + y1 for x1, y1 in it.product(x, y)])) 

     return pd.Series(results) 

    # take this function and apply it to pandas dataframe: 
    df = pd.concat([frame, frame.shift(1)], axis=1)[1:].apply(
     func, axis=1) 

    df.rename(columns={i: x[0] + '_cpst' for i, x in enumerate(labels)}, 
       inplace=True) 
    return pd.concat([frame, df], axis=1) 

Testcode:

import pandas as pd 
from io import StringIO 
data = [x.strip() for x in """ 
     alfa alfa_index beta beta_index delta delta_index 
    0 a,b   23 c,d   36 a,c   32 
    1 a,c   23 b,e   37 c,d   32 
    2 g,h   28 d,f   37 e,g   32 
    3 a,b   28 c,d   39 a,c   34 
    4 c,e   28 b,g   39 d,k   34 
""".split('\n')[1:-1]] 
df = pd.read_csv(StringIO(u'\n'.join(data)), sep='\s+') 
print(df) 

print(crazy_prod_sum_thing(df)) 

Ergebnisse:

alfa alfa_index beta beta_index delta delta_index 
0 a,b   23 c,d   36 a,c   32 
1 a,c   23 b,e   37 c,d   32 
2 g,h   28 d,f   37 e,g   32 
3 a,b   28 c,d   39 a,c   34 
4 c,e   28 b,g   39 d,k   34 

1   [aa,cc, bc,bd,ec,ed, ca,dd] 
2   [ga,gc,ha,hc, db,ff, ec,gg] 
3 [ag,bb, cd,cf,dd,df, ae,ag,ce,cg] 
4    [ca,ee, bc,gg, da,kk] 

Hinweis:

Dadurch wird das Ergebnis nicht wie in der Frage angegeben in einen Datenrahmen zurückversetzt, da ich nicht sicher war, wie die Indexwerte übernommen werden sollen, wenn sie nicht übereinstimmen.

+0

Dies muss etwas praktikabel sein. Ich werde versuchen zu trainieren, wenn es eine Möglichkeit gibt, die Indexwerte zurückzuhalten. Vielen Dank. Ich akzeptiere die Antwort noch nicht vollständig, werde aber in der Zwischenzeit hoffen, dass einige andere Antworten hinzugefügt werden, nur für mein Wissen. Einige Tage warten, um etwas Aufmerksamkeit auf dieses Problem zu bekommen. Vielen Dank. – everestial007

+0

Ich habe gerade versucht den Code, aber es lief in den Fehler während 'print (crazy_prod_sum_thing (df))' ** Fehler msg: ** 'TypeError: (" kann nicht Slice Indizierung auf mit diesen Indexern [6.0] von "," trat bei Index 1 auf ') Es deutet etwas auf den 'float' hin, aber die Indexwerte sollen ganze Zahlen sein. Was könnte das Problem sein? – everestial007

+0

Mit beiden versucht. Ich druckte auch die Ausgabe der Datei, die Sie erstellt und was ich gepostet hatte. Beide sind genau gleich und vom selben Typ. Beide geben genau die gleichen Fehlermeldungen aus. Ich weiß nicht warum? – everestial007

Verwandte Themen