2016-07-22 30 views
0

Ich versuche, eine anscheinend einfache Bedienung in Python zu tun:Pandas: Summe, wenn Spalten Werte übereinstimmt

Ich habe einige Datensätze, sagen 6, und ich möchte die Werte einer Spalte, wenn die Werte summieren der anderen beiden Spalten fällt zusammen. Danach möchte ich die Werte der Spalte, die summiert wurde, durch die Anzahl der Datensätze teilen, die ich in diesem Fall 6 habe (d. H. Berechnen des arithmetischen Mittels). Außerdem möchte ich 0 summieren, wenn die Werte der anderen Spalten nicht übereinstimmen.

Ich schreibe hier zwei Datenrahmen nach unten, als Beispiel:

Code1 Code2 Distance 0 15.0 15.0 2 1 15.0 60.0 3 2 15.0 69.0 2 3 15.0 434.0 1 4 15.0 842.0 0

Code1 Code2 Distance 0 14.0 15.0 4 1 14.0 60.0 7 2 15.0 15.0 0 3 15.0 60.0 1 4 15.0 69.0 9

Die erste Spalte der df.index Spalte ist. Dann möchte ich die Spalte "Abstand" nur addieren, wenn die Spalten "Code1" und "Code2" übereinstimmen. In diesem Fall wäre die gewünschte Ausgabe etwas wie:

Code1 Code2 Distance 0 14.0 15.0 2 1 14.0 60.0 3.5 2 15.0 15.0 1 3 15.0 60.0 2 4 15.0 69.0 5.5 5 15.0 434.0 0.5 6 15.0 842.0 0

Ich habe versucht, dies mit conditionals zu tun, aber für mehr als zwei df ist wirklich schwer zu tun. Gibt es irgendeine Methode in Pandas, um es schneller zu machen?

Jede mögliche Hilfe :-)

+0

Könnte Ihr 'Code1' und' Code2' das gleiche in einem Datenrahmen sein? –

+0

Ich bin mir nicht sicher, ob ich verstehe, möchten Sie die Werte der Entfernung Spalte hinzufügen, wenn Code1 UND Code2 miteinander übereinstimmen? zwischen dfs? unabhängig vom Index? Außerdem, wenn Sie N DataFrames alle mit den gleichen Spalten haben, warum können Sie nicht einfach ein großes df mit allen Daten erstellen und etwas wie sum col where condition verwenden? – nico

+0

@AntonProtopopov, ja, könnte das gleiche sein. –

Antwort

1

geschätzt werden Sie alle Frames Ihre Daten in einer Liste setzen könnte und reduce dann entweder zu append oder merge sie verwenden alle. Werfen Sie einen Blick auf reduzieren here.

Zunächst werden einige Funktionen für die Generierung von Beispieldaten definiert.

import pandas 
import numpy as np 

# GENERATE DATA 
# Code 1 between 13 and 15 
def generate_code_1(n): 
    return np.floor(np.random.rand(n,1) * 3 + 13) 

# Code 2 between 1 and 1000 
def generate_code_2(n): 
    return np.floor(np.random.rand(n,1) * 1000) + 1 

# Distance between 0 and 9 
def generate_distance(n): 
    return np.floor(np.random.rand(n,1) * 10) 

# Generate a data frame as hstack of 3 arrays 
def generate_data_frame(n): 
    data = np.hstack([ 
     generate_code_1(n) 
     ,generate_code_2(n) 
     ,generate_distance(n) 
    ]) 
    df = pandas.DataFrame(data=data, columns=['Code 1', 'Code 2', 'Distance']) 
    # Remove possible duplications of Code 1 and Code 2. Take smallest distance in case of duplications. 
    # Duplications will break merge method however will not break append method 
    df = df.groupby(['Code 1', 'Code 2'], as_index=False) 
    df = df.aggregate(np.min) 
    return df 

# Generate n data frames each with m rows in a list 
def generate_data_frames(n, m, with_count=False): 
    df_list = [] 
    for k in range(0, n): 
     df = generate_data_frame(m) 
     # Add count column, needed for merge method to keep track of how many cases we have seen 
     if with_count: 
      df['Count'] = 1 
     df_list.append(df) 
    return df_list 

Append-Methode (schneller, kürzer, schöner)

df_list = generate_data_frames(94, 5) 

# Append all data frames together using reduce 
df_append = reduce(lambda df_1, df_2 : df_1.append(df_2), df_list) 

# Aggregate by Code 1 and Code 2 
df_append_grouped = df_append.groupby(['Code 1', 'Code 2'], as_index=False) 
df_append_result = df_append_grouped.aggregate(np.mean) 
df_append_result 

Merge Methode

df_list = generate_data_frames(94, 5, with_count=True) 

# Function to be passed to reduce. Merge 2 data frames and update Distance and Count 
def merge_dfs(df_1, df_2): 
    df = pandas.merge(df_1, df_2, on=['Code 1', 'Code 2'], how='outer', suffixes=('', '_y')) 
    df = df.fillna(0) 
    df['Distance'] = df['Distance'] + df['Distance_y'] 
    df['Count'] = df['Count'] + df['Count_y'] 
    del df['Distance_y'] 
    del df['Count_y'] 
    return df 

# Use reduce to apply merge over the list of data frames 
df_merge_result = reduce(merge_dfs, df_list) 

# Replace distance with its mean and drop Count 
df_merge_result['Distance'] = df_merge_result['Distance']/df_merge_result['Count'] 
del df_merge_result['Count'] 
df_merge_result 
Verwandte Themen