988 Stimmen

Kombinieren Sie zwei Textspalten im Pandas-Datenrahmen

Ich habe ein 20 x 4000 DataFrame in Python mit pandas. Zwei dieser Spalten sind mit Jahr und Quartal benannt. Ich würde gerne eine Variable namens period erstellen, die aus Jahr = 2000 und Quartal = q2 2000q2 macht.

Kann mir jemand dabei helfen?

12voto

Colin Wang Punkte 671

Effizienter ist

def concat_df_str1(df):
    """ Laufzeit: 1.3416s """
    return pd.Series([''.join(row.astype(str)) for row in df.values], index=df.index)

und hier ist ein Zeittest:

import numpy as np
import pandas as pd

from time import time

def concat_df_str1(df):
    """ Laufzeit: 1.3416s """
    return pd.Series([''.join(row.astype(str)) for row in df.values], index=df.index)

def concat_df_str2(df):
    """ Laufzeit: 5.2758s """
    return df.astype(str).sum(axis=1)

def concat_df_str3(df):
    """ Laufzeit: 5.0076s """
    df = df.astype(str)
    return df[0] + df[1] + df[2] + df[3] + df[4] + \
           df[5] + df[6] + df[7] + df[8] + df[9]

def concat_df_str4(df):
    """ Laufzeit: 7.8624s """
    return df.astype(str).apply(lambda x: ''.join(x), axis=1)

def main():
    df = pd.DataFrame(np.zeros(1000000).reshape(100000, 10))
    df = df.astype(int)

    time1 = time()
    df_en = concat_df_str4(df)
    print('Laufzeit: %.4fs' % (time() - time1))
    print(df_en.head(10))

if __name__ == '__main__':
    main()

Abschließend, wenn sum(concat_df_str2) verwendet wird, wird das Ergebnis nicht einfach zusammengesetzt, es wird in eine Ganzzahl umgewandelt.

7voto

Anton vBR Punkte 16653

Die Verwendung von zip könnte noch schneller sein:

df["period"] = [''.join(i) for i in zip(df["Year"].map(str),df["quarter"])]

Grafik:

Bildbeschreibung hier eingeben

import pandas as pd
import numpy as np
import timeit
import matplotlib.pyplot as plt
from collections import defaultdict

df = pd.DataFrame({'Year': ['2014', '2015'], 'quarter': ['q1', 'q2']})

myfuncs = {
"df['Year'].astype(str) + df['quarter']":
    lambda: df['Year'].astype(str) + df['quarter'],
"df['Year'].map(str) + df['quarter']":
    lambda: df['Year'].map(str) + df['quarter'],
"df.Year.str.cat(df.quarter)":
    lambda: df.Year.str.cat(df.quarter),
"df.loc[:, ['Year','quarter']].astype(str).sum(axis=1)":
    lambda: df.loc[:, ['Year','quarter']].astype(str).sum(axis=1),
"df[['Year','quarter']].astype(str).sum(axis=1)":
    lambda: df[['Year','quarter']].astype(str).sum(axis=1),
    "df[['Year','quarter']].apply(lambda x : '{}{}'.format(x[0],x[1]), axis=1)":
    lambda: df[['Year','quarter']].apply(lambda x : '{}{}'.format(x[0],x[1]), axis=1),
    "[''.join(i) for i in zip(dataframe['Year'].map(str),dataframe['quarter'])]":
    lambda: [''.join(i) for i in zip(df["Year"].map(str),df["quarter"])]
}

d = defaultdict(dict)
step = 10
cont = True
while cont:
    lendf = len(df); print(lendf)
    for k,v in myfuncs.items():
        iters = 1
        t = 0
        while t < 0.2:
            ts = timeit.repeat(v, number=iters, repeat=3)
            t = min(ts)
            iters *= 10
        d[k][lendf] = t/iters
        if t > 2: cont = False
    df = pd.concat([df]*step)

pd.DataFrame(d).plot().legend(loc='upper center', bbox_to_anchor=(0.5, -0.15))
plt.yscale('log'); plt.xscale('log'); plt.ylabel('Sekunden'); plt.xlabel('df Zeilen')
plt.show()

7voto

Markus Dutschke Punkte 6917

Diese Lösung verwendet einen Zwischenschritt zum Komprimieren von zwei Spalten des DataFrame zu einer einzelnen Spalte, die eine Liste von Werten enthält. Dies funktioniert nicht nur für Strings, sondern für alle Arten von Spalten-Datentypen.

import pandas as pd
df = pd.DataFrame({'Year': ['2014', '2015'], 'quarter': ['q1', 'q2']})
df['list']=df[['Year','quarter']].values.tolist()
df['period']=df['list'].apply(''.join)
print(df)

Ergebnis:

   Year quarter        list  period
0  2014      q1  [2014, q1]  2014q1
1  2015      q2  [2015, q2]  2015q2

7voto

Good Will Punkte 1053

Hier ist meine Zusammenfassung der obigen Lösungen zum Verketten / Kombinieren von zwei Spalten mit int- und str-Werten in einer neuen Spalte unter Verwendung eines Trennzeichens zwischen den Werten der Spalten. Drei Lösungen funktionieren zu diesem Zweck.

# Seien Sie vorsichtig mit dem Trennzeichen, einige Symbole können zu einem "SyntaxError: EOL while scanning string literal" führen.
# z.B. ";;" als Trennzeichen würde den Syntaxfehler verursachen

separator = "&&" 

# Die Methode pd.Series.str.cat() funktioniert nicht, um zwei Spalten mit int-Wert und str-Wert zu verketten / kombinieren. Dies würde einen "AttributeError: Can only use .cat accessor with a 'category' dtype" verursachen

df["period"] = df["Year"].map(str) + separator + df["quarter"]
df["period"] = df[['Year','quarter']].apply(lambda x : '{} && {}'.format(x[0],x[1]), axis=1)
df["period"] = df.apply(lambda x: f'{x["Year"]} && {x["quarter"]}', axis=1)

5voto

leo Punkte 333

Mein Ansatz....

listofcols = ['Spalte1','Spalte2','Spalte3']
df['kombinierte_Spalten'] = ''

for Spalte in listofcols:
    df['kombinierte_Spalten'] = df['kombinierte_Spalten'] + ' ' + df[Spalte]
'''

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X