Pandas wandeln einige Spalten in Zeilen um


113

Mein Datensatz enthält also einige Informationen nach Standort für n Daten. Das Problem ist, dass jedes Datum tatsächlich eine andere Spaltenüberschrift ist. Zum Beispiel sieht die CSV so aus

location    name    Jan-2010    Feb-2010    March-2010
A           "test"  12          20          30
B           "foo"   18          20          25

Ich möchte, dass es so aussieht

location    name    Date        Value
A           "test"  Jan-2010    12       
A           "test"  Feb-2010    20
A           "test"  March-2010  30
B           "foo"   Jan-2010    18       
B           "foo"   Feb-2010    20
B           "foo"   March-2010  25

Problem ist, ich weiß nicht, wie viele Daten in der Spalte sind (obwohl ich weiß, dass sie immer nach dem Namen beginnen)


Antworten:


205

UPDATE
Ab Version 0.20 meltist eine Funktion erster Ordnung, die Sie jetzt verwenden können

df.melt(id_vars=["location", "name"], 
        var_name="Date", 
        value_name="Value")

  location    name        Date  Value
0        A  "test"    Jan-2010     12
1        B   "foo"    Jan-2010     18
2        A  "test"    Feb-2010     20
3        B   "foo"    Feb-2010     20
4        A  "test"  March-2010     30
5        B   "foo"  March-2010     25

ALTE (ER) VERSIONEN: <0,20

Sie können verwenden pd.melt, um den größten Teil des Weges dorthin zu gelangen, und dann sortieren:

>>> df
  location  name  Jan-2010  Feb-2010  March-2010
0        A  test        12        20          30
1        B   foo        18        20          25
>>> df2 = pd.melt(df, id_vars=["location", "name"], 
                  var_name="Date", value_name="Value")
>>> df2
  location  name        Date  Value
0        A  test    Jan-2010     12
1        B   foo    Jan-2010     18
2        A  test    Feb-2010     20
3        B   foo    Feb-2010     20
4        A  test  March-2010     30
5        B   foo  March-2010     25
>>> df2 = df2.sort(["location", "name"])
>>> df2
  location  name        Date  Value
0        A  test    Jan-2010     12
2        A  test    Feb-2010     20
4        A  test  March-2010     30
1        B   foo    Jan-2010     18
3        B   foo    Feb-2010     20
5        B   foo  March-2010     25

(Vielleicht möchten Sie ein werfen .reset_index(drop=True), nur um die Ausgabe sauber zu halten.)

Hinweis : pd.DataFrame.sort wurde zugunsten von abgelehntpd.DataFrame.sort_values .


@DSM was wäre die Umkehrung dieser Funktion. dh wie würde man df2[zurück] zudf
3kstc

1
@ 3kstc Versuchen Sie es hier oder hier . Sie wollen sich mit Drehpunkten befassen. Möglicherweise pandas.pivot_table(df2,values='Value',index=['location','name'],columns='Date').reset_index().
Teepeemm

1
@DSM gibt es eine Möglichkeit, rückwärts zu gehen? Das bedeutet, dass ich viele Zeilen mit demselben Namen habe und ich möchte, dass alle Daten in verschiedenen Spalten stehen
Adrian

17

Verwenden Sie set_indexmit stackfür MultiIndex Series, dann zum DataFrameHinzufügen reset_indexmit rename:

df1 = (df.set_index(["location", "name"])
         .stack()
         .reset_index(name='Value')
         .rename(columns={'level_2':'Date'}))
print (df1)
  location  name        Date  Value
0        A  test    Jan-2010     12
1        A  test    Feb-2010     20
2        A  test  March-2010     30
3        B   foo    Jan-2010     18
4        B   foo    Feb-2010     20
5        B   foo  March-2010     25

5

Ich denke, ich habe eine einfachere Lösung gefunden

temp1 = pd.melt(df1, id_vars=["location"], var_name='Date', value_name='Value')
temp2 = pd.melt(df1, id_vars=["name"], var_name='Date', value_name='Value')

Concat ganz temp1mit temp2's Spaltename

temp1['new_column'] = temp2['name']

Sie haben jetzt das, wonach Sie gefragt haben.


3

pd.wide_to_long

Sie können Ihren Jahresspalten ein Präfix hinzufügen und dann direkt an füttern pd.wide_to_long. Ich werde nicht so tun, als wäre dies effizient , aber es kann in bestimmten Situationen bequemer sein, als pd.meltwenn Ihre Spalten bereits ein geeignetes Präfix haben.

df.columns = np.hstack((df.columns[:2], df.columns[2:].map(lambda x: f'Value{x}')))

res = pd.wide_to_long(df, stubnames=['Value'], i='name', j='Date').reset_index()\
        .sort_values(['location', 'name'])

print(res)

   name        Date location  Value
0  test    Jan-2010        A     12
2  test    Feb-2010        A     20
4  test  March-2010        A     30
1   foo    Jan-2010        B     18
3   foo    Feb-2010        B     20
5   foo  March-2010        B     25
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.