2016-02-21 5 views
0

Мой вопрос лучше всего можно пояснить визуально. Есть много ответов о том, как в кадре данных Pandas удалять строки с определенными значениями столбцов, но я не уверен, что лучший способ справиться с другими шагами того, что я хочу сделать.Pandas: падение строк со значением столбца и удаление других подземельков

country series 2005 2006 2007 2008 2009 

AFG  net m .. .. 5 .. 10 
AFG  battle 100 50 55 60 100 
AFG  GDP 200 100 150 200 250 
AFG  info .. .. .. .. .. 
AFG  life 60 .. 61 63 64 
AFG  unemp 5.7 5.9 6.0 5.4 5.3 
ALB  net m .. .. 5 .. 10 
ALB  battle 100 50 55 60 100 
ALB  GDP 200 100 150 200 250 
ALB  info .. 45 .. 99 .. 
ALB  life 78 .. 61 63 64 
ALB  unemp .. .. .. .. 3.2 
and so on for other countries 

Я хотел бы проверить серию для каждой страны, где для столбца каждый год существует как минимум 2 значения. Если существует менее 2 значений, удалите эту строку. Но если он удаляется для одной страны, удалите его для всех других стран, если это условие не соответствует действительности для этой страны.

Мой результат будет:

country series 2005 2006 2007 2008 2009 

AFG  net m .. .. 5 .. 10 
AFG  battle 100 50 55 60 100 
AFG  GDP 200 100 150 200 250 
AFG  life 60 .. 61 63 64 
ALB  net m .. .. 5 .. 10 
ALB  battle 100 50 55 60 100 
ALB  GDP 200 100 150 200 250 
ALB  life 78 .. 61 63 64 

где информация удаляется для AFG, потому что не было никаких значений в год столбцах, но и для ALB и все другие страны. безработный был удален, потому что для ALB существовало только одно значение, но также было удалено для всех других стран.

Спасибо за ваше время и любой обратной связи

+0

Большое спасибо всем - StackOverflow является удивительным. Все решения работали, и я понял их все. В итоге получается, что для всех стран, которые у меня есть, получается 5 строк (т. Е. 5 имеют по крайней мере 2 значения для каждой страны), это также помогает мне выяснить, в каких странах я могу исключить и иметь более 5 функций – KBA

ответ

1
import pandas as pd 
import numpy as np 
df1 = pd.DataFrame({ 
'2005': ['..', '100', '200', '..', '60', '5.7', '..', '100', '200', '..', '78', '..'], 
'2006': ['..', '50', '100', '..', '..', '5.9', '..', '50', '100', '45', '..', '..'], 
'2007': ['5', '55', '150', '..', '61', '6.0', '5', '55', '150', '..', '61','..'], 
'2008': ['..', '60', '200', '..', '63', '5.4', '..', '60', '200', '99', '63', '..'], 
'2009': ['10', '100', '250', '..', '64', '5.3', '10', '100', '250', '..', '64', '3.2'], 
'country': ['AFG', 'AFG', 'AFG', 'AFG', 'AFG', 'AFG', 'ALB', 'ALB', 'ALB', 'ALB', 'ALB', 'ALB'], 
'series': ['net m', 'battle', 'GDP', 'info', 'life', 'unemp', 'net m', 'battle', 'GDP', 'info', 'life', 'unemp']}, 
columns=['country', 'series', '2005', '2006', '2007', '2008', '2009']).replace('..', np.nan) 

Я выбираю, чтобы сделать фиктивный столбец под названием Count, чтобы просто визуально показать, какие строки удалить, если их Count меньше 2.

df1['Count'] = df1.loc[:, '2005':].count(axis=1) 
    country series 2005 2006 2007 2008 2009 Count 
0  AFG net m NaN NaN 5 NaN 10  2 
1  AFG battle 100 50 55 60 100  5 
2  AFG  GDP 200 100 150 200 250  5 
3  AFG info NaN NaN NaN NaN NaN  0 
4  AFG life 60 NaN 61 63 64  4 
5  AFG unemp 5.7 5.9 6.0 5.4 5.3  5 
6  ALB net m NaN NaN 5 NaN 10  2 
7  ALB battle 100 50 55 60 100  5 
8  ALB  GDP 200 100 150 200 250  5 
9  ALB info NaN 45 NaN 99 NaN  2 
10  ALB life 78 NaN 61 63 64  4 
11  ALB unemp NaN NaN NaN NaN 3.2  1 

Далее следует проверить, если значение series находится в списке значений, связанных со строками, которые имеют Count менее 2. Затем ~ исключает их из результата.

df1[~df1['series'].isin(df1[df1['Count'] < 2]['series'].tolist())] 
#Produces: 
    country series 2005 2006 2007 2008 2009 Count 
0  AFG net m NaN NaN 5 NaN 10  2 
1  AFG battle 100 50 55 60 100  5 
2  AFG  GDP 200 100 150 200 250  5 
4  AFG life 60 NaN 61 63 64  4 
6  ALB net m NaN NaN 5 NaN 10  2 
7  ALB battle 100 50 55 60 100  5 
8  ALB  GDP 200 100 150 200 250  5 
10  ALB life 78 NaN 61 63 64  4 
1
df1 = pd.DataFrame([["AFG", "net m", "", "", 5, "", 10], 
         ["AFG", "battle", 100, 50 , 55, 60 , 100], 
        ["AFG", "GDP", 200, 100 , 150, 200 , 250], 
         ["AFG", "info", "", "" , "", "" , ""], 
         ["AFG", "life", 60, "" , 61, 63 , 64], 
         ["ALB", "net m", "", "", 5, "", 10], 
         ["ALB", "battle", 100, 50 , 55, 60 , 100], 
        ["ALB", "GDP", 200, 100 , 150, 200 , 250], 
         ["ALB", "info", "", 45 , "", 99 , ""], 

         ["ALB", "life", 78, "" , 61, 63 , 64], 

        ],columns = ["country", "series", 2005,2006,2007,2008,2009]) 
list_of_series_to_exclude = [] 
for i in df1["country"].unique(): #loop over unique countries 
    for row in df1[df1["country"]==i].iterrows(): #loop over a slice of original dataframe, based on current country 
     series = row[1][1] # keep track of current series 
     years = pd.Series([x for x in row[1][2:]]) # year columns 
     x = dict(years.value_counts(sort=True)) # get in dictionary form the counts for unique values in the year columns 
     try: 
      if x[''] > len(row[1][2:])-2: 
       list_of_series_to_exclude.append(series) 
     except KeyError: 
      pass #Row doesnt have blank value 
final_set = set(df1["series"]) 
set_to_sub = set(list_of_series_to_exclude) 

final_list = list(final_set-set_to_sub) 
df1 = df1[df1["series"].isin(final_list)]   

Выход:

print df1 
country series 2005 2006 2007 2008 2009 
0  AFG net m    5  10 
1  AFG battle 100 50 55 60 100 
2  AFG  GDP 200 100 150 200 250 
4  AFG life 60  61 63 64 
5  ALB net m    5  10 
6  ALB battle 100 50 55 60 100 
7  ALB  GDP 200 100 150 200 250 
9  ALB life 78  61 63 64 
1

Я полагаю, что пустые поля представлены в виде NaNs. Вы можете сначала использовать isnull и sum для извлечения строк менее двух допустимых значений, и использовать соответствующие значения «серии», чтобы фильтровать исходный DataFrame с isin:

mask = (~df[range(2005,2010)].isnull()).sum(axis=1) < 2 
print df[~df.series.isin(df[mask].series)] 

Выход:

country series 2005 2006 2007 2008 2009 
0  AFG net m NaN NaN  5 NaN 10 
1  AFG battle 100 50 55 60 100 
2  AFG  GDP 200 100 150 200 250 
4  AFG life 60 NaN 61 63 64 
5  ALB net m NaN NaN  5 NaN 10 
6  ALB battle 100 50 55 60 100 
7  ALB  GDP 200 100 150 200 250 
9  ALB life 78 NaN 61 63 64 
Смежные вопросы