在groupby数据框

时间:2015-10-14 00:12:20

标签: python-2.7 pandas

我有一个如下所示的数据框df

key_1, key_2, country
12, a, US
12, a, US
12, b, US
12, c, NZ
23, d, PE
23, e, PE
23, e, PE
31, f, RO
31, f, RO
42, g, VI

我对满足以下条件的2个数据帧(请为每个数据帧提供一个过程)感兴趣:

1st-给予key_1,有一个唯一的key_2 AND个唯一的国家/地区。例如。

23, d, PE
23, e, PE

第二 - 给予一个key_1,有多个唯一的key_2 AND多个唯一的国家/地区。例如。

12, a, US
12, b, US
12, c, NZ

在这两种情况下,生成的数据框都应具有唯一的行。

现在已经读了一段时间的其他问题,但我最接近的是:

result = df.groupby("key_1")["key_2"].apply(pd.value_counts).count(level=0)

这有助于我找到哪些行具有多个唯一的" key_2key_1" (我的大部分数据框都是由一个唯一的key_2和每个key_1行的国家/地区组成,无论重复如何),但我还远远不能满足我的要求。

非常感谢您提前! (对不起问题标题,但我不知道该怎么称呼它)

3 个答案:

答案 0 :(得分:1)

经过几个小时的挖掘,我终于成功了。任何有更好解决方案的人都欢迎回答!

我在我的真实数据框架上尝试了以下代码,但它确实有效。

正如@Alexander正确指出的那样,"您所需的两个数据帧都建立在同一组数据上:对于给定的key_1具有多个key_2的行_"

因此,对于给定key_1的具有多个唯一key_2的行,我首先进行子集化。然后我将它分为2:一个用于给一个key_1的唯一国家,另一个用于超过2个国家给一个key_1。

# more than one unique key_2 per key_1
subset_k2= df.groupby(['key_1'])['key_2'].nunique().reset_index()
subset_k2= subset_gb[subset_gb[key_2] > 1]
subset_all= df[df["key_1"].isin(subset_k2["key_1"].tolist())]

# more than one unique country per key_1
subset_ct= df.groupby(['key_1'])['country'].nunique().reset_index()
subset_ct= subset_ct[subset_ct['country'] > 1]

# Results that fulfill condition 2 from my question:
result_2 = subset_all[subset_all["key_1"].isin(subset_ct["key_1"].tolist())].drop_duplicates()

# Results that fulfill condition 1 from my question:
result_1 = subset_all[~subset_all["key_1"].isin(subset_ct["key_1"].tolist())].drop_duplicates()

答案 1 :(得分:0)

您可以使用get_groups和drop_duplicates:

In [11]: g = df.groupby("key_1")

In [12]: g.get_group(12).drop_duplicates()
Out[12]:
   key_1 key_2 country
0     12     a      US
2     12     b      US
3     12     c      NZ

In [13]: g.get_group(23).drop_duplicates()
Out[13]:
   key_1 key_2 country
4     23     d      PE
5     23     e      PE

答案 2 :(得分:0)

您所需的两个数据框都建立在同一组数据上:给定key_2的行数超过key_1

首先,我们会在key_1上进行分组并计算key_2个值。我们创建了一个名为keys的列表,其中key_2计数大于一。

然后使用这些键过滤原始数据帧。

接下来,我们会将国家/地区计数(在key_1key_2上分组)合并到数据框中。

最后,我们根据它的country_count值(即等于1且大于1)来拆分此数据帧。

from collections import Counter

# Create sample data.
df = pd.DataFrame({'key_1': [12,12,12,12,23,23,23,31,31,42], 
                   'key_2': list('aabcdeeffg'), 
                   'country': ['US', 'US', 'US', 'NZ', 'PE', 'PE', 'PE', 'RO', 'RO', 'VI']})

# Get list of key pairs where there are more than one `key_2` for a given `key_1`
gb1 = df.groupby(['key_1', 'key_2']).key_2.count()
keys = gb1[gb1 > 1].index.tolist()

# Filter the dataframe for the correct keys.
idx = [n for n, pair in enumerate(zip(df.key_1, df.key_2)) if pair in keys]
df_temp = df.ix[idx]

# Get the country count for each `key_`1 / `key_2' pair.
gb1 = df_temp.groupby('key_1').key_2.apply(Counter)
df_temp = pd.DataFrame(gb1.reset_index().values, columns=['key_1', 'key_2', 'country_count'])
df_temp = df.merge(df_temp, on=['key_1', 'key_2'])

# More than one unique `key_2` for a given `key_1` and only one country.
df1 = df_temp.loc[df_temp.country_count == 1, ['key_1', 'key_2', 'country']]

# More than one unique `key_2` for a given `key_1` and more than one country.
df2 = df_temp.loc[df_temp.country_count > 1, ['key_1', 'key_2', 'country']]