Mam dataframe o nazwie celu. Ta dataframe ma kolumnę o nazwie "CNAE2".

Jeśli ja print(target.CNAE2) Dostaję:

id
3                                                       NaN
7                                                       NaN
17           50.30-1-02, 52.11-7-01, 52.32-0-00, 52.50-8-05
18                                               32.67-1-00
19                                   46.93-1-00, 49.40-0-00
20                                                      NaN

Wartości nie-Nan kolumny są ciągi. Oni obejmią pewną logikę relacyjną, moim zamiarem jest wykonanie następujących czynności: a) Przekręć go w listy b) złamać je na wielu poziomach (nazywam to "Pai", "VO", "Bisavo") i oddziel różne kolumny

id                                  CNAE2                     CNAE2pai                CNAE2vo   CNAE2bisavo
3                                     NaN                          NaN                    NaN           NaN  
7                                     NaN                          NaN                    NaN           NaN  
17   [50.30-1-02, 52.32-0-00, 52.50-8-05]  [50.30-1, 52.32-0, 52.50-8]  [50.30, 52.32, 52.50]  [50, 52, 52]
18                           [32.67-1-00]                    [32.67-1]                [32.67]          [32]
19               [46.93-1-00, 46.40-0-00]           [46.93-1, 46.40-0]         [46.93, 46.40]      [46, 46]
20                                    NaN                          NaN                    NaN           NaN 

Udało mi się osiągnąć ten wynik, mój kod liczy się na wielu pętlach, a ponieważ prowadzę dość dużą dataframe, potrzeba na zawsze. Nie jest opłacalny. Użyłem następującego kodu:

    for i in target.index:
        cnaes=str(target['CNAE2'][i]).split(', ')
        target.CNAE2[i]=cnaes
        if cnaes == ['nan'] or cnaes == 'NaN' or cnaes == "":
            target.CNAE2[i]='NaN'
        else:
            target.CNAE2pai[i]=[]
            target.CNAE2vo[i]=[]
            target.CNAE2bisavo[i]=[]

            for k in range(len(cnaes)):
                y=cnaes[k][:7]
                target['CNAE2pai'][i].append(y)
            for k in range(len(cnaes)):
                y=cnaes[k][:5]
                target['CNAE2vo'][i].append(y)
            for k in range(len(cnaes)):
                y=cnaes[k][:2]
                target['CNAE2bisavo'][i].append(y)
            target.CNAE2pai[i]=list(set(target.CNAE2pai[i]))
            target.CNAE2vo[i]=list(set(target.CNAE2vo[i]))
            target.CNAE2bisavo[i]=list(set(target.CNAE2bisavo[i]))

Czy ktoś może zasugerować bardziej skuteczny sposób na osiągnięcie tego wyniku?

0
aabujamra 25 czerwiec 2017, 17:48

3 odpowiedzi

Najlepsza odpowiedź
s = target.CNAE2.str.split(', ', expand=True).stack()

pai = s.str.rsplit('-', 1).str[0].groupby(level=0).apply(list)
vo = s.str.split('-', 1).str[0].groupby(level=0).apply(list)
bisavo = s.str.split('.').str[0].groupby(level=0).apply(list)
base = s.groupby(level=0).apply(list)

pd.concat(
    [base, pai, vo, bisavo], axis=1,
    keys=['', 'pai', 'vo', 'bisavo']
).add_prefix('CNAE2').reindex(target.index)

                                               CNAE2                              CNAE2pai                       CNAE2vo       CNAE2bisavo
id                                                                                                                                        
3                                                NaN                                   NaN                           NaN               NaN
7                                                NaN                                   NaN                           NaN               NaN
17  [50.30-1-02, 52.11-7-01, 52.32-0-00, 52.50-8-05]  [50.30-1, 52.11-7, 52.32-0, 52.50-8]  [50.30, 52.11, 52.32, 52.50]  [50, 52, 52, 52]
18                                      [32.67-1-00]                             [32.67-1]                       [32.67]              [32]
19                          [46.93-1-00, 49.40-0-00]                    [46.93-1, 49.40-0]                [46.93, 49.40]          [46, 49]
20                                               NaN                                   NaN                           NaN               NaN
1
piRSquared 25 czerwiec 2017, 16:09

Nie próbowałem tego, ale prawdopodobnie lepiej uniknąć .Append. Lepiej najpierw wykonać listę i dołączyć do tego, a gdy wynik zostanie zakończony, wprowadź go do Dataframe.

1
Bastiaan 25 czerwiec 2017, 15:10

Użyłem tutaj funkcji apply, co powinno być szybsze niż rzędami, {X1}} Lookup, który powinien być szybszy niż Twoja lub funkcja i ostatecznie wymienia się, które mają tendencję do szybszego niż zagnieżdżona {x2}} pętla . Nie przetestowałem tego, ale mam nadzieję, że pomoże.

import pandas as pd

# Create dummy data and  dataframe
d = {"3":"NaN","7":"NaN","17":"50.30-1-02, 52.11-7-01, 52.32-0-00, 52.50-8-05","18":"32.67-1-00",
     "19":"46.93-1-00, 49.40-0-00","20":"NaN"}
target = pd.DataFrame([[k, d[k]] for k in d], columns = ["id","CNAE"])

# Loop across desired columns
nans = set(["nan","NaN",""])
for col in [("CNAE2pai",7),("CNAE2vo",5),("CNAE2bisavo",2)]:
    target[col[0]] = target.CNAE.apply(lambda x: "NaN" if x in nans else [i[:col[1]] for i in x.split(", ")])
target["CNAE2"] = target.CNAE.apply(lambda x: "NaN" if x in nans else [i for i in x.split(", ")])

EDYTOWAĆ

W moim systemie, wykorzystywania lambda Funkcja i zrozumienie daje szybsze wyniki niż groupby:

d = {"3":"NaN","7":"NaN","17":"50.30-1-02, 52.11-7-01, 52.32-0-00, 52.50-8-05","18":"32.67-1-00",
     "19":"46.93-1-00, 49.40-0-00","20":"NaN"}
target = pd.DataFrame([[k, d[k]] for k in d], columns = ["id","CNAE"])

def lambda_func(target):
    # Loop across desired columns
    nans = set(["nan","NaN",""])
    for col in [("CNAE2pai",7),("CNAE2vo",5),("CNAE2bisavo",2)]:
        target[col[0]] = target.CNAE.apply(lambda x: "NaN" if x in nans else [i[:col[1]] for i in x.split(", ")])
    target["CNAE2"] = target.CNAE.apply(lambda x: "NaN" if x in nans else [i for i in x.split(", ")])
    return target

def groupby_func(target):
    s = target.CNAE.str.split(', ', expand=True).stack()

    pai = s.str.rsplit('-', 1).str[0].groupby(level=0).apply(list)
    vo = s.str.split('-', 1).str[0].groupby(level=0).apply(list)
    bisavo = s.str.split('.').str[0].groupby(level=0).apply(list)
    base = s.groupby(level=0).apply(list)

    target = pd.concat(
        [base, pai, vo, bisavo], axis=1,
        keys=['', 'pai', 'vo', 'bisavo']
    ).add_prefix('CNAE2').reindex(target.index)

    return target

Prowadzi do:

%timeit lambda_func(target) 1000 loops, best of 3: 930 µs per loop
%timeit groupby_func(target) 100 loops, best of 3: 6.3 ms per loop
2
Matt 25 czerwiec 2017, 22:33