python - 选择数据框的一个子集,每个变量都有 N 年的数据值(value)

标签 python pandas dataframe

我有一个数据集显示 100 多个国家/地区从 1970 年到 2013 年的年度增长指标。并非所有国家/地区都有所有年份的数据,年份最少的国家/地区有 30 年的数据。我想把事情弄平,让所有国家向我展示 30 年的数据,从超过 30 年的国家中删除年份。我在下面提供了一个例子。

我考虑过使用循环从数据框中删除数据,直到所有国家/地区出现 30 次,然后构建一个全新的数据框,但我相信有更好的解决方案。

import pandas as pd

data = {'Country':['Israel','Congo','Denmark',
                   'Israel','Denmark',
                   'Israel','Congo',
                   'Israel','Congo','Denmark'],
        'Year':[2000,2000,2000,
                2001,2001,
                2002,2002,
                2003,2003,2003],
        'Value':[2.5,1.2,3.1,2.8,1.1,2.9,3.1,1.9,3.0,3.1]}
df = pd.DataFrame(data=data)
df
   Country  Year  Value
0   Israel  2000    2.5
1    Congo  2000    1.2
2  Denmark  2000    3.1
3   Israel  2001    2.8
4  Denmark  2001    1.1
5   Israel  2002    2.9
6    Congo  2002    3.1
7   Israel  2003    1.9
8    Congo  2003    3.0
9  Denmark  2003    3.1

上面的代码创建了一个数据框,其中仅使用 3 个国家和 4 年的示例。从数据框中,您可以看到以色列有 4 年的数据,而丹麦和刚果只有 3 年。我想从以色列中删除一年,以便所有国家/地区都有 3 年。在真实的数据框中,我想从超过 30 年的国家中删除年份,以便所有国家都具有相同的年份,最好删除值最小的年份。

这是我使用 for 循环的解决方案,它使用了很多行代码:

gp = df.groupby('Country').groups #Group by country name
d = {} #Build dictionary Country Name => index list.

for i in gp: #Iterate over all countries until a list of 3 indeces is 
#reached for each country.
    d[i] = []
    for j in gp[i]:
        if len(d[i])<3: #A country appears once every year in the dataset,
#3 means 3 years. If a country appears more than 3 times, it will only 
#include the indices of the first 3 occurrences. 
            d[i].append(j)
indeces = [] #Gather the indeces to keep in the dataframe.
for i in d:
    for j in d[i]:
        if len(d[i])==3: #make sure the list has exactly 3 items
            indeces.append(j)

final_df = df.loc[indeces,['Country','Year','Value']]
final_df
#Now I have one less value for Israel, so all countries have 3 values.
   Country  Year  Value
1    Congo  2000    1.2
6    Congo  2002    3.1
8    Congo  2003    3.0
2  Denmark  2000    3.1
4  Denmark  2001    1.1
9  Denmark  2003    3.1
0   Israel  2000    2.5
3   Israel  2001    2.8
5   Israel  2002    2.9

最佳答案

您可以根据年份列中的唯一值创建最近几年的列表,并使用 bool 索引为使用该列表的数据框编制索引。

recent_years = df.Year.unique()[-3:]
df[df.Year.isin(recent_years)]

    Country Year    Value
3   Israel  2001    2.8
4   Denmark 2001    1.1
5   Israel  2002    2.9
6   Congo   2002    3.1
7   Israel  2003    1.9
8   Congo   2003    3.0
9   Denmark 2003    3.1

如果您的 Year 值不一定按顺序排列,请使用 numpy unique 返回排序数组,这与 pandas unique() 不同

recent_years = np.unique(df.Year)[-3:]
df[df.Year.isin(recent_years)]

这是另一个解决方案,它返回每个国家最近 3 年的数据。如果数据没有按年份排序,需要先排序。

idx = df.groupby('Country').apply(lambda x: x['Year'].tail(3)).index
df.set_index(['Country', df.index]).reindex(idx).reset_index().drop('level_1', 1)

    Country Year    Value
0   Congo   2000    1.2
1   Congo   2002    3.1
2   Congo   2003    3.0
3   Denmark 2000    3.1
4   Denmark 2001    1.1
5   Denmark 2003    3.1
6   Israel  2001    2.8
7   Israel  2002    2.9
8   Israel  2003    1.9

如果数据没有排序,先使用排序

df = df.sort_values(by = 'Year')

关于python - 选择数据框的一个子集,每个变量都有 N 年的数据值(value),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54599633/

相关文章:

python - Python 中的多重继承

python - 处理大数据进行随机森林分类

python - 将日常 Excel 数据组织到 xarray 数据集中

Python Pandas Dataframe : Nested JSON to columns, 查询 1 列并返回相应的单元格值

python - 如何映射多列python

python - 将列表中的值分配到字典中

python - 根据现有列的部分字符串内容向新的 Pandas 数据框列添加值

python - 对 Django 查询集进行单元测试

python - 使用变量在循环中从 DataFrame 中提取数据

python - 可以生成大型 Pandas 数据框 View 的 bool 索引?