Bereiten Sie zunächst den folgenden Datenrahmen vor.
Vorbereitung von DataFrame
import pandas as pd
values = [['1', 'John', 'somekey1-1', 'somevalue1-1', 'time1-1', 'somekey2-1', 'somevalue2-1', 'time2-1'],
['2', 'Tom', 'somekey1-2', 'somevalue1-2', 'time1-2', 'somekey2-2', 'somevalue2-2', 'time2-2'],]
df = pd.DataFrame(values, columns=['id', 'name', 'key1', 'value1', 'time1', 'key2', 'value2', 'time2'])
df
Die folgenden Daten werden mit dem obigen Code erstellt.
id | name | key1 | value1 | time1 | key2 | value2 | time2 | |
---|---|---|---|---|---|---|---|---|
0 | 1 | John | somekey1-1 | somevalue1-1 | time1-1 | somekey2-1 | somevalue2-1 | time2-1 |
1 | 2 | Tom | somekey1-2 | somevalue1-2 | time1-2 | somekey2-2 | somevalue2-2 | time2-2 |
Ich werde vier Codes einführen, die diese Informationen in vertikal gehaltene Daten konvertieren, wie unten gezeigt.
id | name | key | value | time | |
---|---|---|---|---|---|
0 | 1 | John | somekey1-1 | somevalue1-1 | time1-1 |
1 | 2 | Tom | somekey1-2 | somevalue1-2 | time1-2 |
2 | 1 | John | somekey2-1 | somevalue2-1 | time2-1 |
3 | 2 | Tom | somekey2-2 | somevalue2-2 | time2-2 |
Es scheint, dass es üblich ist, die Schmelzmethode zu verwenden, und diese Informationen waren reichlich vorhanden. Es gibt verschiedene Möglichkeiten, ein Array von Spalten zu erstellen, daher werde ich dies auch einschließen.
Erstellen Sie ein Array mit Spaltennamen
#Muster ①
columns = df.columns.tolist()
[value for value in columns if value.startswith('key')]
#Muster ②
df.columns[df.columns.str.startswith('key')].tolist()
#Ergebnis
# ['key1', 'key2']
Das Muster ①, das ein Spaltenarray einmal erstellt und verschiebt, scheint sich also leichter zu bewegen Ich benutze das unten.
Mit Schmelze in vertikale Daten konvertieren
columns = df.columns.tolist()
pd.concat(
[pd.melt(df, id_vars=['id', 'name'], value_vars=[value for value in columns if value.startswith('key')], value_name='key'),
pd.melt(df, value_vars=[value for value in columns if value.startswith('value')], value_name='value'),
pd.melt(df, value_vars=[value for value in columns if value.startswith('time')], value_name='time')
],
axis=1
).drop('variable', axis=1)
wide_to_long ist ziemlich einfach, da Sie es in einer Zeile erstellen können. Ich habe es zuerst nicht verstanden, als ich mir die Seite unten angesehen habe. https://pandas.pydata.org/docs/reference/api/pandas.wide_to_long.html
Konvertieren Sie in dem durch das zweite Argument angegebenen Array eine Spalte, die mit einem bestimmten Zeichen beginnt, in vertikales Halten Da es sich so bewegt, ist es möglich, es in einer Zeile zu vervollständigen.
Der verbleibende Teil der Spalte wird durch "j" angegeben Wenn es "key1" ist, erstellen Sie es mit dem angegebenen Spaltennamen, und wenn es "key2" ist, erstellen Sie es mit "2". Im folgenden Code wird eine Spalte mit dem Namen "drop" erstellt. Danach wird sie mit der Methode "drop" gelöscht.
wide_to_Konvertieren Sie mit long in vertikale Daten
pd.wide_to_long(df, ['key','value','time'], i='id', j='drop').reset_index().drop('drop', axis=1)
Was tun, wenn der folgende Fehler angezeigt wird? Der folgende Fehler tritt auf, wenn doppelte ID-Elemente vorhanden sind.
error
ValueError: the id variables need to uniquely identify each row
Wenn Sie beispielsweise den ersten Datenrahmen ein wenig ändern und ihn mit beiden auf "1" gesetzten IDs ausführen, wird eine Fehlermeldung angezeigt.
DataFrame mit einem Fehler
import pandas as pd
values = [['1', 'John', 'somekey1-1', 'somevalue1-1', 'time1-1', 'somekey2-1', 'somevalue2-1', 'time2-1'],
['1', 'Tom', 'somekey1-2', 'somevalue1-2', 'time1-2', 'somekey2-2', 'somevalue2-2', 'time2-2'],]
df = pd.DataFrame(values, columns=['id', 'name', 'key1', 'value1', 'time1', 'key2', 'value2', 'time2'])
pd.wide_to_long(df,['key','value','time'], i='id', j='drop').reset_index().drop('drop', axis=1)
In diesem Fall können Sie es lösen, indem Sie ein Indexelement mit reset_index ()
erstellen und es in id angeben.
wide_to_Konvertieren Sie mit long in vertikale Daten(Methode zur Fehlervermeidung)
pd.wide_to_long(df.reset_index(), ['key','value','time'], i='index', j='drop').reset_index().drop('drop', axis=1).drop('index', axis=1)
lreshape
scheint eine untergeordnete Methode zu sein, die behoben werden kann, um umformen
zu können, selbst wenn Sie auf Google suchen.
Persönlich mag ich es, weil es einfach ist, aber die folgende Seite sagt, dass es in Zukunft verschwinden wird, so dass es scheint, dass es nicht bald verwendbar sein wird. Es tut uns leid.
https://pandas.pydata.org/pandas-docs/version/1.0.0/whatsnew/v1.0.0.html
Mit lreshape in vertikale Daten konvertieren
d = {'key': df.columns[df.columns.str.startswith('key')].tolist(),
'value': df.columns[df.columns.str.startswith('value')].tolist(),
'time': df.columns[df.columns.str.startswith('time')].tolist(),}
pd.lreshape(df, d)
Auch wenn geschrieben werden sollte, dass es in der Praxis verwendet wird, aus irgendeinem Grund das Folgende Es scheint besser, es nicht zu oft zu verwenden, da es Fehler verursachen kann.
error
/usr/local/lib/python3.6/dist-packages/pandas/core/reshape/melt.py in <dictcomp>(.0)
188 mask &= notna(mdata[c])
189 if not mask.all():
--> 190 mdata = {k: v[mask] for k, v in mdata.items()}
191
192 return data._constructor(mdata, columns=id_cols + pivot_cols)
IndexError: boolean index did not match indexed array along dimension 0; dimension is 1210 but corresponding boolean dimension is 24200
Wahrscheinlich nicht ganz gut. Als ich die obige Methode zuerst nicht kannte, habe ich es getan.
Bei Verwendung der concat-Methode, wenn die Spaltennamen identisch sind Es ist eine Methode, um es zu verwenden, da es vertikal verbunden wird.
Implementierung mit concat
pd.concat([
df[['id', 'name', 'key1', 'value1', 'time1']].rename(columns={'key1': 'key', 'value1': 'value', 'time1': 'time'}),
df[['id', 'name', 'key2', 'value2', 'time2']].rename(columns={'key2': 'key', 'value2': 'value', 'time2': 'time'}),
])
Recommended Posts