Pandas Dataframe neu erstellen

Nov 05 2020

Ich bin ziemlich neu in Python. Ich habe Probleme mit der Rekonstruktion eines schlechten Datenrahmens. Mein Datenrahmen sieht folgendermaßen aus:

df = pd.DataFrame({'col1': ['id 1', 'id 2', 'test 3', 'test 4'],
               'col2': ['test 1', 'test 2',
                        'Number 6135', 'id 4'],
               'col3': ['Number 12344', 'Number 21612','id 3','Number 1131']})

Wie Sie sehen können, habe ich die "IDs" in der ersten, zweiten und Thrid-Spalte. Gleiches gilt für die anderen Werte.

Mein Ziel ist es, einen Datenrahmen zu haben, in dem jeder Col nur die Werte hat, die mit dem gleichen Teilstring wie in diesem Beispiel beginnen:

Ich habe bereits versucht, for-Schleifen und if-Anweisungen zu verwenden, um zu überprüfen, ob sich ein bestimmter Teilstring in meinem String befindet. Wenn das stimmt, erstelle ich eine neue Spalte und schreibe meinen Wert hinein

for x in df['col1']:
if 'id' in x:
    df['newCol']=x

Ich weiß, dass dieser Code mein Problem niemals lösen wird. Vielleicht gibt es einige Pandas-Funktionen, die mir helfen können, dieses Problem zu lösen

Wenn etwas nicht klar ist, frag mich einfach, ich werde mein Bestes geben, um mein Problem zu erklären. Vielen Dank im Voraus für Ihre Hilfe und schonen Sie mich :)

Antworten

3 AndrejKesely Nov 05 2020 at 17:34

Sie können sorted()mit benutzerdefinierten Tastenfunktion verwenden:

def key_fn(x):
    if 'id' in x:
        return 0
    if 'test' in x:
        return 1
    if 'Number' in x:
        return 2
    return 3 

df = df.apply(lambda x: pd.Series(sorted(x, key=key_fn)), axis=1)
df = df.rename(columns=lambda x: 'col{}'.format(x+1))
print(df)

Drucke:

   col1    col2          col3
0  id 1  test 1  Number 12344
1  id 2  test 2  Number 21612
2  id 3  test 3   Number 6135
3  id 4  test 4   Number 1131

Eine andere Version aus den Kommentaren:

df = pd.DataFrame([sorted(l, key=key_fn) for l in df.values], columns=df.columns)
print(df)
3 jezrael Nov 05 2020 at 17:34

Wenn möglich, vereinfachen Sie die Lösung, indem Sie die Werte durch das erste Leerzeichen teilen:

df = (df.reset_index()
        .melt('index')
        .assign(new = lambda x: x['value'].str.split().str[0])
        .pivot('index','new','value'))
print (df)
new          Number    id    test
index                            
0      Number 12344  id 1  test 1
1      Number 21612  id 2  test 2
2       Number 6135  id 3  test 3
3       Number 1131  id 4  test 4

Sonst können Sie verwenden Series.str.extract:

L = ['id','test','Number']

df = (df.reset_index()
        .melt('index')
        .assign(new = lambda x: x['value'].str.extract(f'({"|".join(L)})', expand=False))
        .pivot('index','new','value'))
print (df)
new          Number    id    test
index                            
0      Number 12344  id 1  test 1
1      Number 21612  id 2  test 2
2       Number 6135  id 3  test 3
3       Number 1131  id 4  test 4
AndyL. Nov 05 2020 at 17:38

Versuche dies:

s = df.melt()['value']
df_final = pd.DataFrame({x: s[s.str.startswith(x)].values 
                                        for x in s.str.split().str[0].unique()})

Out[27]:
     id    test        Number
0  id 1  test 3   Number 6135
1  id 2  test 4  Number 12344
2  id 4  test 1  Number 21612
3  id 3  test 2   Number 1131
sammywemmy Nov 05 2020 at 17:48

Sie können zuerst den Datenrahmen schmelzen , dann mit numpy select die Namen neu anordnen und schließlich schwenken :

(df.melt(ignore_index=False)
   .assign(variable=lambda x: np.select([x.value.str.startswith("id"),
                                          x.value.str.startswith("test"),
                                          x.value.str.startswith("Number")],
                                          ["col1", "col2", "col3"]))
    .reset_index()
    .pivot("index", "variable", "value")
    .rename_axis(columns=None, index=None))


    col1    col2    col3
0   id 1    test 1  Number 12344
1   id 2    test 2  Number 21612
2   id 3    test 3  Number 6135
3   id 4    test 4  Number 1131