【问题标题】:How to add rows in a data frame using a loop with conditions如何使用带条件的循环在数据框中添加行
【发布时间】:2020-08-22 00:18:04
【问题描述】:

''' 我正在用熊猫编写代码。卡在下面我需要使用缺失行的部分。 ''' 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 年缺失年份的空白行 ''' 期望的输出:

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

【问题讨论】:

  • 欢迎您!您能否展示您解决问题的尝试?
  • 我创建了一个不同的数据框,其中包含所有年份。尝试使用左连接加入,但我无法在所有国家/地区都这样做
  • 我也尝试过使用列表。我创建了一个包含所有年份的列表。编写了一个函数来检查 D 列是否包含该列表中的值。如果是,则忽略它,如果不是,则添加一行,其中缺少年份和国家/地区。但似乎循环在熊猫中不起作用
  • 这可能不是最好的方法,但是如何:附加所有要添加的行(如9 US BENIN 2004),对DataFrame进行排序,删除具有缺失值的重复项,然后重置索引?
  • 这只是我数据框的一小部分。我的数据框包含超过 60000 行,我需要为所有 B 和 C 对添加缺失年份

标签: python pandas function loops dataframe


【解决方案1】:

新解决方案:

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

【讨论】:

  • 感谢您提供此代码但我需要为每个 B 和 C 对添加从 1995 年到 2005 年缺失的空白行。
  • ABCDEFGH 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 20美国贝宁 2002 8 美国贝宁 2003 9 美国贝宁 2004 10 美国贝宁 2005
  • 此解决方案适合您吗?另外,如果它确实适合您的用例,请接受答案。
【解决方案2】:

我不确定这有多优化,但既然您询问了有关此方法的详细信息,就在这里。

假设您有要添加到 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

【讨论】:

  • 感谢您的代码。但是我没有 DF_to _add 数据框,因为数据库太大并且
  • “我也尝试过使用列表。我创建了一个包含所有年份的列表。”我认为这意味着你有这些数据。 R Bute 的回答不适合你吗?
  • 是的,R Bute 的回答有效。谢谢大家的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-23
  • 2022-01-03
  • 2019-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多