2015-11-13 22 views
5

mam plik CSV z wierszy wyglądać tak:danych munging w pand

ID,98.4,100M,55M,65M,75M,100M,75M,65M,100M,98M,100M,100M,92M,0#,0N#, 

mogę go czytać z

#!/usr/bin/env python 

import pandas as pd 
import sys 

filename = sys.argv[1] 
df = pd.read_csv(filename) 

Biorąc pod uwagę szczególny kolumna, chciałbym podzielić wiersze przez ID, a następnie wyprowadzić średnią i odchylenie standardowe dla każdego ID.

Mój pierwszy problem polega na tym, jak usunąć wszystkie nieliczbowe części z takich liczb, jak "100M" i "0N #", które powinny wynosić odpowiednio 100 i 0.

Próbowałem też zapętlenie nad odpowiednimi nagłówkami i korzystania

df[header].replace(regex=True,inplace=True,to_replace=r'\D',value=r'') 

jak zasugerowano w Pandas DataFrame: remove unwanted parts from strings in a column.

zmienia to jednak 98,4 do 984.

+0

Możliwy duplikat [pandy DataFrame: usunąć niechciane elementy z ciągów znaków w kolumnie] (http: // stackoverflow.com/questions/13682044/pandas-dataframe-remove-unwanted-parts-from-strings-in-a-column) – Evert

+0

@Evert Dodano edycję, aby pokazać, w jaki sposób muszę radzić sobie z przecinkami dziesiętnymi. – eleanora

+0

Duplikat podany na liście sugeruje użycie 'rstrip', z znakami, które chciałbyś usunąć. Więc ... 'rstrip ('MN #')' powinno działać ładnie dla twojego wejścia, używając lambda zasugerowanego w duplikacie (oczywiście, możesz pominąć część 'lstrip'). – Evert

Odpowiedz

3

użycie str.extract:

In [356]: 
import io 
import pandas as pd 
t="""ID,98.4,100M,55M,65M,75M,100M,75M,65M,100M,98M,100M,100M,92M,0#,0N#""" 
df = pd.read_csv(io.StringIO(t), header=None) 
df 

Out[356]: 
    0  1  2 3 4 5  6 7 8  9 10 11 12 13 \ 
0 ID 98.4 100M 55M 65M 75M 100M 75M 65M 100M 98M 100M 100M 92M 

    14 15 
0 0# 0N# 

In [357]: 
for col in df.columns[2:]: 
    df[col] = df[col].str.extract(r'(\d+)').astype(int) 
df 

Out[357]: 
    0  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 
0 ID 98.4 100 55 65 75 100 75 65 100 98 100 100 92 0 0 

Jeśli masz liczb zmiennoprzecinkowych Następnie można użyć następującego wyrażenia regularnego:

In [379]: 
t="""ID,98.4,100.50M,55.234M,65M,75M,100M,75M,65M,100M,98M,100M,100M,92M,0#,0N#""" 
df = pd.read_csv(io.StringIO(t), header=None) 
df 

Out[379]: 
    0  1  2  3 4 5  6 7 8  9 10 11 \ 
0 ID 98.4 100.50M 55.234M 65M 75M 100M 75M 65M 100M 98M 100M 

    12 13 14 15 
0 100M 92M 0# 0N# 

In [380]:  
for col in df.columns[2:]: 
    df[col] = df[col].str.extract(r'(\d+\.?\d+)').astype(np.float) 
df 

Out[380]: 
    0  1  2  3 4 5 6 7 8 9 10 11 12 13 14 15 
0 ID 98.4 100.5 55.234 65 75 100 75 65 100 98 100 100 92 NaN NaN 

tak (\d+\.?\d+) wygląda dla grup zawierające \d+ 1 lub więcej cyfr zopcjonalnym punktem dziesiętnym i \d+ 1 lub więcej kolejnych cyfr po przecinku

EDIT

OK edytowane mój regex wzoru:

In [408]: 
t="""Name,97.7,0A,0A,65M,0A,100M,5M,75M,100M,90M,90M,99M,90M,0#,0N#""" 
df = pd.read_csv(io.StringIO(t), header=None) 
df 

Out[408]: 
    0  1 2 3 4 5  6 7 8  9 10 11 12 13 14 \ 
0 Name 97.7 0A 0A 65M 0A 100M 5M 75M 100M 90M 90M 99M 90M 0# 

    15 
0 0N# 

In [409]:  
for col in df.columns[2:]: 
    df[col] = df[col].str.extract(r'(\d+\.*\d*)').astype(np.float) 
df 

Out[409]: 
    0  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 
0 Name 97.7 0 0 65 0 100 5 75 100 90 90 99 90 0 0 
+0

df = pd.read_csv (io.StringIO (t), nagłówek = brak) TypeError: wartość_wartość musi być w formacie Unicode lub None, a nie str – eleanora

+0

Zignorować bit 'io.StringIO' to właśnie przeczytałem w tekście jako obiekt pliku w twoim przypadku 'df = pd.read_csv (nazwa pliku)' jest w porządku – EdChum

+0

Jeśli jest to cały plik "Nazwa", 97,07A, 0A, 65M, 0A, 100M, 5M, 75M, 100M, 90M, 90M, 99M, 90M, 0 #, 0N #, "Twój kod daje mi" 0 Nazwa NaN NaN NaN 65 NaN 100 NaN 75 100 90 90 99 90 NaN NaN NaN " – eleanora

2

My first problem is, how can I remove all the non-numeric parts from the numbers such as "100M" and "0N#" which should be 100 and 0 respectively.

import re 
df = pd.read_csv(yourfile, header=None) 
df.columns = ['ID'] + list(df.columns)[1:] 
df = df.stack().apply(lambda v: re.sub('[^0-9]','', v) 
       if isinstance(v, str) else v).astype(float).unstack() 
df.groupby('ID').agg(['std', 'mean']) 

Tutaj .stack() przemienia dataframe w serialu .apply() wywołuje lambda dla każdej wartości, re.sub() usuwa wszelkie nieliczbowe znaki, .astype() konwertuje na numeryczny, a unstack() przekształca serię z powrotem w ramkę danych. Działa to równie dobrze zarówno dla liczb całkowitych, jak i liczb zmiennoprzecinkowych.

Given a particular column, I would like to split the rows by ID and then output the mean and standard deviation for each ID.

# for all columns 
df.groupby('ID').agg(['std', 'mean']) 
# for specific column 
df.groupby('ID')['<colname>'].agg(['std', 'mean']) 

output dataframe

Oto dane użyte w tym przykładzie:

from StringIO import StringIO 
s=""" 
1,98.4,100M,55M,65M,75M,100M,75M,65M,100M,98M,100M,100M,92M,0#,0N#, 
1,98.4,100M,55M,65M,75M,100M,75M,65M,100M,98M,100M,100M,92M,0#,0N#, 
2,98.4,100M,55M,65M,75M,100M,75M,65M,100M,98M,100M,100M,92M,0#,0N#, 
2,98.4,100M,55M,65M,75M,100M,75M,65M,100M,98M,100M,100M,92M,0#,0N#, 
""" 
yourfile = StringIO(s)