Как добавить строки во фрейм данных, используя al oop с условиями - PullRequest
0 голосов
/ 07 мая 2020

'' 'Я пишу код на pandas. Застрял в нижней части, где мне нужно использовать недостающие строки. '' 'df

A B      C         D    E  E   G  H
0 US   BENIN      1995  5  10  15 40
1 US   BENIN      1996  6  12  12 12
2 US   BENIN      2000  4  13  12 12
3 US   Hungary    1998  5  19  23 23
4 US   Hungary    1999  3  23  12 3
5 UK   Chile      2000  5  10  15 40
6 UK   Chile      2002  6  12  12 12
7 UK   Chile      2004  4  13  12 12
8 UK   Iceland    2004  5  19  23 23
89UK   Iceland    2005  3  23  12 3

' '' Я хочу добавить пустые строки за отсутствующие годы с 1995 по 2000 между этими строками, используя al oop '' ' Желаемый результат:

A B     C           D   E  F   G  H
0 US   BENIN      1995  5  10  15 40
1 US   BENIN      1996  6  12  12 12
2 US   BENIN      1997
3 US   BENIN      1998
4 US   BENIN      1999     
5 US   BENIN      2000  4  13  12 12
6 US   BENIN      2001
7 US   BENIN      2002
8 US   BENIN      2003
9 US   BENIN      2004
10US   BENIN      2005
11US   Hungary    1995
12US   Hungary    1996
13US   Hungary    1997
14US   Hungary    1998  5  19  23 23
15US   Hungary    1999  3  23  12 3
16US   Hungary    1999
17US   Hungary    2000
18US   Hungary    2001
19US   Hungary    2002
20US   Hungary    2003
21US   Hungary    2004
22US   Hungary    2005
23UK   Chile      1995 
24UK   Chile      1996 
25UK   Chile      1997 
26UK   Chile      1998 
27UK   Chile      1999 
28UK   Chile      2000  5  10  15 40
29UK   Chile      2001 
30UK   Chile      2002  6  12  12 12
31UK   Chile      2003 
32UK   Chile      2004  4  13  12 12
33UK   Chile      2005

:
:
:
: 
43 UK   Iceland    2004  5  19  23 23
44 UK   Iceland    2005  3  23  12 3

Ответы [ 2 ]

1 голос
/ 07 мая 2020

Новое решение:

import re

import pandas as pd

df: pd.DataFrame = pd.DataFrame([
    re.match('(\w+)\ +(\w+)\ +(\w+)\ +(\w+)\ +(\w+)\ +(\w+)\ +(\w+)\ +(\w+)', data).groups() for data in '''
A B      C         D    E  E   G  H
0 US   BENIN      1995  5  10  15 40
1 US   BENIN      1996  6  12  12 12
2 US   BENIN      2000  4  13  12 12
3 US   Hungary    1998  5  19  23 23
4 US   Hungary    1999  3  23  12 3
5 UK   Chile      2000  5  10  15 40
6 UK   Chile      2002  6  12  12 12
7 UK   Chile      2004  4  13  12 12
8 UK   Iceland    2004  5  19  23 23
89 UK   Iceland    2005  3  23  12 3
'''.split('\n')[1:-1]
], dtype='int32')


def consolidate(index, year_min, year_max):
    indexes: list = []
    last_country, last_county, last_year = None, None, year_min
    for country, county, year in index:
        for yr in range(last_year, year):
            indexes.append((country, county, yr))
        last_country, last_county, last_year = country, county, year
    if last_year <= year_max:
        for yr in range(last_year, year_max + 1):
            indexes.append((last_country, last_county, yr))
    return indexes


df.columns = df.iloc[0, :]
df = df.iloc[1:, :]
df.iloc[:, -5] = df.D.astype('int')
df = df.sort_values(['D', 'C'])
year_min, year_max = df.D.min(), df.D.max()
df.set_index(['B', 'C', 'D'], inplace=True)
df1 = df.groupby(['B', 'C']).apply(lambda x: x.reindex(consolidate(x.index, year_min, year_max)))
df1.index = df1.index.droplevel([0, 1])
df = df1.reset_index()
if __name__ == '__main__':
    print(df)

# 0    B        C     D    A    E    E    G    H
# 0   UK    Chile  1995  NaN  NaN  NaN  NaN  NaN
# 1   UK    Chile  1996  NaN  NaN  NaN  NaN  NaN
# 2   UK    Chile  1997  NaN  NaN  NaN  NaN  NaN
# 3   UK    Chile  1998  NaN  NaN  NaN  NaN  NaN
# 4   UK    Chile  1999  NaN  NaN  NaN  NaN  NaN
# 5   UK    Chile  2000    5    5   10   15   40
# 6   UK    Chile  2001  NaN  NaN  NaN  NaN  NaN
# 7   UK    Chile  2002    6    6   12   12   12
# 8   UK    Chile  2003  NaN  NaN  NaN  NaN  NaN
# 9   UK    Chile  2004    7    4   13   12   12
# 10  UK    Chile  2005  NaN  NaN  NaN  NaN  NaN
# 11  UK  Iceland  1995  NaN  NaN  NaN  NaN  NaN
# 12  UK  Iceland  1996  NaN  NaN  NaN  NaN  NaN
# 13  UK  Iceland  1997  NaN  NaN  NaN  NaN  NaN
# 14  UK  Iceland  1998  NaN  NaN  NaN  NaN  NaN
# 15  UK  Iceland  1999  NaN  NaN  NaN  NaN  NaN
# 16  UK  Iceland  2000  NaN  NaN  NaN  NaN  NaN
# 17  UK  Iceland  2001  NaN  NaN  NaN  NaN  NaN
# 18  UK  Iceland  2002  NaN  NaN  NaN  NaN  NaN
# 19  UK  Iceland  2003  NaN  NaN  NaN  NaN  NaN
# 20  UK  Iceland  2004    8    5   19   23   23
# 21  UK  Iceland  2005   89    3   23   12    3
# 22  US    BENIN  1995    0    5   10   15   40
# 23  US    BENIN  1996    1    6   12   12   12
# 24  US    BENIN  1997  NaN  NaN  NaN  NaN  NaN
# 25  US    BENIN  1998  NaN  NaN  NaN  NaN  NaN
# 26  US    BENIN  1999  NaN  NaN  NaN  NaN  NaN
# 27  US    BENIN  2000    2    4   13   12   12
# 28  US    BENIN  2001  NaN  NaN  NaN  NaN  NaN
# 29  US    BENIN  2002  NaN  NaN  NaN  NaN  NaN
# 30  US    BENIN  2003  NaN  NaN  NaN  NaN  NaN
# 31  US    BENIN  2004  NaN  NaN  NaN  NaN  NaN
# 32  US    BENIN  2005  NaN  NaN  NaN  NaN  NaN
# 33  US  Hungary  1995  NaN  NaN  NaN  NaN  NaN
# 34  US  Hungary  1996  NaN  NaN  NaN  NaN  NaN
# 35  US  Hungary  1997  NaN  NaN  NaN  NaN  NaN
# 36  US  Hungary  1998    3    5   19   23   23
# 37  US  Hungary  1999    4    3   23   12    3
# 38  US  Hungary  2000  NaN  NaN  NaN  NaN  NaN
# 39  US  Hungary  2001  NaN  NaN  NaN  NaN  NaN
# 40  US  Hungary  2002  NaN  NaN  NaN  NaN  NaN
# 41  US  Hungary  2003  NaN  NaN  NaN  NaN  NaN
# 42  US  Hungary  2004  NaN  NaN  NaN  NaN  NaN
# 43  US  Hungary  2005  NaN  NaN  NaN  NaN  NaN
0 голосов
/ 08 мая 2020

Я не уверен, насколько это оптимально, но поскольку вы запросили подробности об этом подходе, вот оно.

Предполагая, что у вас есть данные, которые вы хотите добавить в DataFrame, например:

print(df_to_add)
#     B        C     D
# 0  US  Hungary  1995
# 1  US  Hungary  1996
# 2  US  Hungary  1997
# 3  US  Hungary  1998
# 4  US  Hungary  1999
# .
# .
# .
# 39  UK  Iceland  2001
# 40  UK  Iceland  2002
# 41  UK  Iceland  2003
# 42  UK  Iceland  2004
# 43  UK  Iceland  2005

И ваши данные в DataFrame:

print(df.head())
#    A   B        C     D  E   F   G   H
# 0  0  US    BENIN  1995  5  10  15  40
# 1  1  US    BENIN  1996  6  12  12  12
# 2  2  US    BENIN  2000  4  13  12  12
# 3  3  US  Hungary  1998  5  19  23  23
# 4  4  US  Hungary  1999  3  23  12   3

Это должно сделать то, что вы просили:

# Concatenate the data
df = pd.concat([df, df_to_add])
df = df.sort_values(by=['B', 'C', 'D']).reset_index(drop=True)
df['A'] = df.index.values

# remove nan duplicates
def filter_dup_nans(df: DataFrame, row):
    # if it's a duplicate
    if df[(df['B'] == row['B']) & (df['C'] == row['C']) & (df['D'] == row['D'])].shape[0] > 1:
        # return false if it's the nan one
        return not row.isnull().values.any()
    # not a duplicate -> don't remove it
    return True

to_remove = list(filter(lambda i: i >= 0, map(lambda row: row[0] if not filter_dup_nans(
    df, row[1]) else -1, df.iterrows())))
df = df.drop(to_remove).reset_index(drop=True)
df['A'] = df.index.values
print(df)

Печать:

     A   B        C     D    E     F     G     H
0    0  UK    Chile  1995  NaN   NaN   NaN   NaN
1    1  UK    Chile  1996  NaN   NaN   NaN   NaN
2    2  UK    Chile  1997  NaN   NaN   NaN   NaN
3    3  UK    Chile  1998  NaN   NaN   NaN   NaN
4    4  UK    Chile  1999  NaN   NaN   NaN   NaN
5    5  UK    Chile  2000  5.0  10.0  15.0  40.0
6    6  UK    Chile  2001  NaN   NaN   NaN   NaN
7    7  UK    Chile  2002  6.0  12.0  12.0  12.0
8    8  UK    Chile  2003  NaN   NaN   NaN   NaN
9    9  UK    Chile  2004  4.0  13.0  12.0  12.0
10  10  UK    Chile  2005  NaN   NaN   NaN   NaN
11  11  UK  Iceland  1995  NaN   NaN   NaN   NaN
12  12  UK  Iceland  1996  NaN   NaN   NaN   NaN
13  13  UK  Iceland  1997  NaN   NaN   NaN   NaN
14  14  UK  Iceland  1998  NaN   NaN   NaN   NaN
15  15  UK  Iceland  1999  NaN   NaN   NaN   NaN
16  16  UK  Iceland  2000  NaN   NaN   NaN   NaN
17  17  UK  Iceland  2001  NaN   NaN   NaN   NaN
18  18  UK  Iceland  2002  NaN   NaN   NaN   NaN
19  19  UK  Iceland  2003  NaN   NaN   NaN   NaN
20  20  UK  Iceland  2004  5.0  19.0  23.0  23.0
21  21  UK  Iceland  2005  3.0  23.0  12.0   3.0
22  22  US    BENIN  1995  5.0  10.0  15.0  40.0
23  23  US    BENIN  1996  6.0  12.0  12.0  12.0
24  24  US    BENIN  1997  NaN   NaN   NaN   NaN
25  25  US    BENIN  1998  NaN   NaN   NaN   NaN
26  26  US    BENIN  1999  NaN   NaN   NaN   NaN
27  27  US    BENIN  2000  4.0  13.0  12.0  12.0
28  28  US    BENIN  2001  NaN   NaN   NaN   NaN
29  29  US    BENIN  2002  NaN   NaN   NaN   NaN
30  30  US    BENIN  2003  NaN   NaN   NaN   NaN
31  31  US    BENIN  2004  NaN   NaN   NaN   NaN
32  32  US    BENIN  2005  NaN   NaN   NaN   NaN
33  33  US  Hungary  1995  NaN   NaN   NaN   NaN
34  34  US  Hungary  1996  NaN   NaN   NaN   NaN
35  35  US  Hungary  1997  NaN   NaN   NaN   NaN
36  36  US  Hungary  1998  5.0  19.0  23.0  23.0
37  37  US  Hungary  1999  3.0  23.0  12.0   3.0
38  38  US  Hungary  2000  NaN   NaN   NaN   NaN
39  39  US  Hungary  2001  NaN   NaN   NaN   NaN
40  40  US  Hungary  2002  NaN   NaN   NaN   NaN
41  41  US  Hungary  2003  NaN   NaN   NaN   NaN
42  42  US  Hungary  2004  NaN   NaN   NaN   NaN
43  43  US  Hungary  2005  NaN   NaN   NaN   NaN
...