【问题标题】:assign hash to row of categorical data in pandas将哈希分配给熊猫中的分类数据行
【发布时间】:2016-11-05 12:26:32
【问题描述】:

所以我有很多带有 3 列分类变量的 pandas 数据框:

             D              F     False
             T              F     False
             D              F     False
             T              F     False

第一列和第二列可以采用三个值之一。第三个是二进制。所以总共有 18 行可能的行(并非所有组合都可以在每个数据帧上表示)。

我想为每一行分配一个数字 1-18,以便为具有相同因素组合的行分配相同的数字,反之亦然(无哈希冲突)。

在 pandas 中最有效的方法是什么?

所以,all_combination_df 是一个包含所有可能因素组合的 df。我正在尝试将诸如 big_df 之类的 df 转换为其中包含唯一数字的系列

import pandas, itertools

def expand_grid(data_dict):
    """Create a dataframe from every combination of given values."""
    rows = itertools.product(*data_dict.values())
    return pandas.DataFrame.from_records(rows, columns=data_dict.keys())

all_combination_df = expand_grid(
                           {'variable_1': ['D', 'A', 'T'],
                           'variable_2': ['C', 'A', 'B'],
                           'variable_3'     : [True, False]})

big_df = pandas.concat([all_combination_df, all_combination_df, all_combination_df])

【问题讨论】:

  • pandas.DataFrame.to_dict() 如果您首先找到唯一行(删除重复项),则应该这样做。
  • @P-robot:这是问题的一个重要方面。查找唯一的行和 dict() 会花费太多时间(数据很大,而且是成块的)。我知道有 18 种可能的组合。有没有办法使用这些信息?
  • 好的。我懂了。也许您可以创建一个包含 18 种可能组合的字典,然后将这些组合映射到数据?
  • @P-robot:有趣,如何将字典映射到数据框?
  • 我在下面编辑了我的答案,以说明如何使用map

标签: python pandas hash dataframe


【解决方案1】:

更新:@user189035 mentioned in the comment 最好使用分类 dtype,因为它会节省大量内存

我会尝试使用factorize 方法:

In [112]: df['category'] = \
     ...:     pd.Categorical(
     ...:         pd.factorize((df.a + '~' + df.b + '~' + (df.c*1).astype(str)))[0])
     ...:

In [113]: df
Out[113]:
   a  b      c category
0  A  X   True        0
1  B  Y  False        1
2  A  X   True        0
3  C  Z  False        2
4  A  Z   True        3
5  C  Z   True        4
6  B  Y  False        1
7  C  Z  False        2

In [114]: df.dtypes
Out[114]:
a             object
b             object
c               bool
category    category
dtype: object

说明:我们可以通过这种简单的方式将所有列粘贴到一个系列中:

In [115]: df.a + '~' + df.b + '~' + (df.c*1).astype(str)
Out[115]:
0    A~X~1
1    B~Y~0
2    A~X~1
3    C~Z~0
4    A~Z~1
5    C~Z~1
6    B~Y~0
7    C~Z~0
dtype: object

【讨论】:

  • 这就是票!
  • @P-robot,谢谢!现在我知道this idiom 是什么意思了;)
  • 如果 a 列和 b 列在comon 中具有同名的一种模态,是否存在哈希冲突的风险?
  • 一个小评论:如果(像我一样)需要新列的长度与旧列相同,您应该使用:(df.a+~+df.b+~df.c.astype(str)).astype('category')
【解决方案2】:

在不考虑效率问题的情况下,这会找到重复的行并为您提供字典(类似于问题here)。

import pandas as pd, numpy as np

# Define data
d = np.array([["D", "T", "D", "T", "U"], 
["F", "F", "F", "J", "K"], 
[False, False, False, False, True]])
df = pd.DataFrame(d.T)

# Find and remove duplicate rows
df_nodupe = df[~df.duplicated()]

# Make a list
df_nodupe.T.to_dict('list')

{0: ['D', 'F', 'False'],
 1: ['T', 'F', 'False'],
 3: ['T', 'J', 'False'],
 4: ['U', 'K', 'True']}

否则,您可以使用map,如下所示:

import pandas as pd, numpy as np

# Define data
d = np.array([["D", "T", "D", "T", "U"], 
["F", "F", "F", "J", "K"], 
[False, False, False, False, True]])
df = pd.DataFrame(d.T)
df.columns = ['x', 'y', 'z']

# Define your dictionary of interest
dd = {('D', 'F', 'False'): 0,
 ('T', 'F', 'False'): 1,
 ('T', 'J', 'False'): 2,
 ('U', 'K', 'True'): 3}

# Create a tuple of the rows of interest
df['tupe'] = zip(df.x, df.y, df.z)

# Create a new column based on the row values
df['new_category'] = df.tupe.map(dd)

【讨论】:

    猜你喜欢
    • 2023-03-31
    • 2011-07-20
    • 2022-08-04
    • 2017-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-13
    • 2012-01-09
    相关资源
    最近更新 更多