2016-05-27 12 views
0
city  state neighborhoods  categories 
Dravosburg PA  [asas,dfd]   ['Nightlife'] 
Dravosburg PA  [adad]    ['Auto_Repair','Automotive'] 

Ich habe oben Datenrahmen möchte ich jedes Element einer Liste in die Spalte, um zB konvertieren:Converting Liste in Panda Datenrahmen in Spalten

city  state asas dfd adad Nightlife Auto_Repair Automotive 
Dravosburg PA 1  1 0 1   1   0  

Ich verwende folgenden Code, dies zu tun:

def list2columns(df): 
""" 
to convert list in the columns 
of a dataframe 
""" 
columns=['categories','neighborhoods'] 
for col in columns:  
    for i in range(len(df)): 
     for element in eval(df.loc[i,"categories"]): 
      if len(element)!=0: 
       if element not in df.columns: 
        df.loc[:,element]=0 
       else: 
        df.loc[i,element]=1 
  1. Wie geht das effizienter?
  2. Warum noch unter Warnung gibt es, wenn ich df.loc bin schon mit

    SettingWithCopyWarning: A value is trying to be set on a copy of a slice 
    from a DataFrame.Try using .loc[row_indexer,col_indexer] = value instead 
    

Antwort

2

Da Sie eval() verwenden, gehe ich davon aus jede Spalte eine Zeichenfolgendarstellung einer Liste und nicht eine Liste selbst. Im Gegensatz zu Ihrem obigen Beispiel gehe ich davon aus, dass um die Elemente in den Listen in Ihrer neighborhoods Spalte (df.iloc[0, 'neighborhoods'] == "['asas','dfd']") Anführungszeichen stehen, da andernfalls Ihr eval() fehlschlagen würde.

Wenn das alles korrekt ist, könnten Sie so etwas wie dies versuchen:

def list2columns(df): 
""" 
to convert list in the columns of a dataframe 
""" 
columns = ['categories','neighborhoods'] 
new_cols = set()  # list of all new columns added 
for col in columns:  
    for i in range(len(df[col])): 
     # get the list of columns to set 
     set_cols = eval(df.iloc[i, col]) 
     # set the values of these columns to 1 in the current row 
     # (if this causes new columns to be added, other rows will get nans) 
     df.iloc[i, set_cols] = 1 
     # remember which new columns have been added 
     new_cols.update(set_cols) 
# convert any un-set values in the new columns to 0 
df[list(new_cols)].fillna(value=0, inplace=True) 
# if that doesn't work, this may: 
# df.update(df[list(new_cols)].fillna(value=0)) 

ich nur auf eine Antwort auf Ihre zweite Frage, über die SettingWithCopy Warnung spekulieren kann.

Es ist möglich (aber unwahrscheinlich), dass df.iloc statt df.loc mit helfen, dass da durch die Zeilennummer wählen sollte (in Ihrem Fall df.loc[i, col] funktioniert nur, weil Sie keinen Index gesetzt haben, so Pandas den Standard verwendet Index, der der Zeilennummer entspricht).

Eine andere Möglichkeit ist, dass die df, die an Ihre Funktion übergeben wird, bereits ein Stück von einem größeren Dataframe ist, und das verursacht die Warnung SettingWithCopy.

Ich habe auch festgestellt, dass die Verwendung von df.loc mit gemischten Indexierungsmodi (logische Selektoren für Zeilen und Spaltennamen für Spalten) die Warnung SettingWithCopy erzeugt; Es ist möglich, dass Ihre Slice Selectors ähnliche Probleme verursachen.

Hoffentlich löst die einfachere und direktere Indexierung im obigen Code jedes dieser Probleme. Aber melden Sie sich bitte zurück (und stellen Sie Code zur Verfügung, um df zu generieren), wenn Sie diese Warnung immer noch sehen.

2

verwenden stattdessen

def list2columns(df): 
    """ 
    to convert list in the columns 
    of a dataframe 
    """ 
    df = df.copy() 
    columns=['categories','neighborhoods'] 
    for col in columns:  
     for i in range(len(df)): 
      for element in eval(df.loc[i,"categories"]): 
       if len(element)!=0: 
        if element not in df.columns: 
         df.loc[:,element]=0 
        else: 
         df.loc[i,element]=1 
    return df 
Verwandte Themen