【问题标题】:Storing dictionaries inside a dataframe that have duplicate entries in a unique value column将字典存储在唯一值列中具有重复条目的数据框中
【发布时间】:2019-07-09 10:27:40
【问题描述】:

我有一个数据框,其中有一列包含重复值,因为我想要将其转换为仅具有唯一值的多年数据。为此,我希望将其他列转换为字典,将所有年份的数据显示为格式为 {'year': value} 的键值对。必须对除具有唯一值的列之外的所有其他列执行此操作。 我的输入数据框如下所示

Original input data frame

数据框的可重现代码

df = pd.DataFrame({
    'A': {0: 'a1', 1: 'a2', 2: 'a3', 3: 'a4'}, 
    'Unique': {0: 'b1', 1: 'b1', 2: 'b2', 3: 'b2'}, 
    'Year': {0: 2017, 1: 2008, 2: 2017, 3: 2008} , 
    'C': {0: 'c1', 1: 'c2', 2: 'c3', 3: 'c4'}
})

到目前为止,我已经尝试将每个变量的值-年份组合放入列表中,并将其添加到字典中,以期将其转换回数据框。但这不会让我得到与预期输出相同的结果。

到目前为止我所做的示例是

B_list = list(df["Unique"])
temp_dict = {}
new_dict = {}
for a in set(Unique_list):
    i = 0
    new_dict[a] = {}
    temp_list = []
    for index, row in df.iterrows():
        if df["Unique"][i] == a:      
            temp_list.append(str(df["Year"][i]) +": " +  df["A"][i])
            i = i+1
        new_dict[a] = temp_list

输出字典为

{'b1': ['2017: a1', '2008: a2'], 
 'b2': ['2017: a3', '2008: a4']}

当我变成一个数据框时转换为一个

Resulting data frame which is not correct

虽然预期的输出是格式中的数据框

Expected output data frame

有什么帮助吗?提前致谢。

【问题讨论】:

  • 请不要使用屏幕截图,而是将数据框粘贴到代码块中。
  • @RvdBerg 这是我第一次提问。因此,当我尝试嵌入 daraframe 时,它​​会给出一条消息,说我需要 10 个声誉才能这样做。请告诉我是否有其他方法可以做到这一点?
  • 我不认为你想在数据框中使用字典,这是一种反模式。我想你想在这里使用索引。
  • Sachi,你做得很好。只需将数据框作为其值发布在“```” 之间

标签: python pandas dataframe dictionary


【解决方案1】:

为了提高性能,如果大数据最好不要在列中使用字典,但如果是小数据,GroupBy.apply 可以使用自定义函数:

def f(x):
    y = x.pop('Year')
    c = x.columns.difference(['Unique'])
    return pd.concat([pd.Series([dict(zip(y, x[col]))]).rename(col) for col in c], 1)

df1 = (df.groupby('Unique')
         .apply(f)
         .reset_index(level=1, drop=True)
         .rename_axis('B')
         .reset_index()
         .sort_index(axis=1))
print (df1)
                          A   B                         C
0  {2017: 'a1', 2008: 'a2'}  b1  {2017: 'c1', 2008: 'c2'}
1  {2017: 'a3', 2008: 'a4'}  b2  {2017: 'c3', 2008: 'c4'}

更好的解决方案是在列中创建MultiIndex

df1 = df.set_index(['Unique','Year']).unstack()
print (df1)
          A         C     
Year   2008 2017 2008 2017
Unique                    
b1       a2   a1   c2   c1
b2       a4   a3   c4   c3

或者在索引中,这取决于最终需要什么:

df2 = df.set_index(['Unique','Year'])
print (df2)
              A   C
Unique Year        
b1     2017  a1  c1
       2008  a2  c2
b2     2017  a3  c3
       2008  a4  c4

【讨论】:

  • 我了解此方法不适用于大规模数据。请告知如何在不使用字典的情况下解决这种情况。
  • 它按预期工作。感谢您的建议。我认为对于更大的数据集,使用建议的多索引等更有效的方法会很有用。
【解决方案2】:

pandas DataFrame 中使用字典是一种反模式。

假设您希望得到每个唯一 UniqueAYear 值的结果。

我们从你的DataFrame开始:

请注意:您不必为 DataFrame 分配中的列使用字典。你已经可以用这样的列表来简化它了:

df = pd.DataFrame({
    'A': ['a1', 'a2', 'a3', 'a4'], 
    'Unique': ['b1', 'b1', 'b2', 'b2'], 
    'Year': [2017, 2008, 2017, 2008], 
    'C': ['c1', 'c2', 'c3', 'c4']
})

现在您可以通过将 b 设置为索引来选择数据。

df.set_index('Unique', drop=False, inplace=True)

你可以这样做:

In : df2.loc['b1']                                                           
Out: 
         A Unique  Year   C
Unique                     
b1      a1     b1  2017  c1
b1      a2     b1  2008  c2

【讨论】:

  • 我知道使用字典会影响性能。谢谢你的建议。
  • @sachini_rb 这不仅仅是关于性能。在数据框中使用 dicts 会使它变得比它需要的更复杂。按预期使用 DataFrame 将帮助您更快地编写代码,并使其对其他人更具可读性。请花点时间阅读本指南,它会对您有所帮助:pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html
【解决方案3】:

尝试使用 apply 和 zip 来做到这一点

df = pd.DataFrame( {'A': {0: 'a1', 1: 'a2', 2: 'a3', 3: 'a4'},
                    'Unique': {0: 'b1', 1: 'b1', 2: 'b2', 3: 'b2'},
                    'Year': {0: 2017, 1: 2008, 2: 2017, 3: 2008} ,
                    'C': {0: 'c1', 1: 'c2', 2: 'c3', 3: 'c4'}})

def converting_into_dict(grp,col_name,key="Year"):
    return dict(zip(grp[key], grp[col_name]))

res = pd.DataFrame(df.groupby('Unique').apply(lambda x :converting_into_dict(x,"A")),columns=["A"])
res2 = pd.DataFrame(df.groupby('Unique').apply(lambda x :converting_into_dict(x,"C")),columns=["B"])
final_res = pd.merge(res,res2,on=['Unique']).reset_index()
print(final_res)
      Unique         A                         B
0     b1  {2017: 'a1', 2008: 'a2'}  {2017: 'c1', 2008: 'c2'}
1     b2  {2017: 'a3', 2008: 'a4'}  {2017: 'c3', 2008: 'c4'}

希望能解决你的问题

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多