【问题标题】:Create dummies from column with multiple values in pandas从熊猫中具有多个值的列创建假人
【发布时间】:2013-09-24 05:41:47
【问题描述】:

我正在寻找一种pythonic方法来处理以下问题。

pandas.get_dummies() 方法非常适合从数据框的分类列创建虚拟对象。例如,如果列中有 ['A', 'B'] 中的值,get_dummies() 会创建 2 个虚拟变量并相应地分配 0 或 1。

现在,我需要处理这种情况。单列,我们称之为“标签”,具有类似 ['A', 'B', 'C', 'D', 'A*C', 'C*D'] 的值。 get_dummies() 创建了 6 个假人,但我只想要其中的 4 个,这样一行就可以有多个 1。

有没有办法以 Python 的方式处理这个问题?我只能想一些逐步的算法来获得它,但这不包括 get_dummies()。 谢谢

已编辑,希望更清楚!

【问题讨论】:

  • 你不能只选择你想调用get_dummies()的列吗?喜欢df[['A', 'B', 'C','D']].get_dummies()?
  • A、B、C、C*D等,是单列的值。
  • 好的明白,df[df.col.isin(['A','B','C'])].get_dummies() 会这样吗?这将过滤掉您不想为其生成虚拟值的值

标签: python pandas dummy-data categorical-data


【解决方案1】:

您可以使用原始数据生成虚拟数据框,隔离包含给定原子的列,然后将结果匹配存储回原子列。

df
Out[28]: 
  label
0     A
1     B
2     C
3     D
4   A*C
5   C*D

dummies = pd.get_dummies(df['label'])

atom_col = [c for c in dummies.columns if '*' not in c]

for col in atom_col:
    ...:     df[col] = dummies[[c for c in dummies.columns if col in c]].sum(axis=1)
    ...:     

df
Out[32]: 
  label  A  B  C  D
0     A  1  0  0  0
1     B  0  1  0  0
2     C  0  0  1  0
3     D  0  0  0  1
4   A*C  1  0  1  0
5   C*D  0  0  1  1

【讨论】:

  • 像魅力一样工作! (尽管您需要在代码中将 'd' 编辑为 'dummies')非常感谢!
  • 我刚刚发现,如果“标签”变量的值采用[A,B,C,D,A*C,C*D,E*F] 形式,则该解决方案不起作用。无论如何,我让它工作的方式是:atom_col = '*'.join(pd.Series(df['label'])).split('*').unique()(它在 1 行中很丑,但步骤都在那里)
  • 你也可以使用集合推导:atom_col = {c for raw_c in dummies.columns for c in raw_c.split('*') if '*' not in c}
【解决方案2】:

我有一个更清洁的解决方案。假设我们要转换以下数据框

   pageid category
0       0        a
1       0        b
2       1        a
3       1        c

进入

        a  b  c
pageid         
0       1  1  0
1       1  0  1

一种方法是使用 scikit-learn 的 DictVectorizer。不过,我有兴趣了解其他方法。

df = pd.DataFrame(dict(pageid=[0, 0, 1, 1], category=['a', 'b', 'a', 'c']))

grouped = df.groupby('pageid').category.apply(lambda lst: tuple((k, 1) for k in lst))
category_dicts = [dict(tuples) for tuples in grouped]
v = sklearn.feature_extraction.DictVectorizer(sparse=False)
X = v.fit_transform(category_dicts)

pd.DataFrame(X, columns=v.get_feature_names(), index=grouped.index)

【讨论】:

    【解决方案3】:

    我知道这个问题被问到已经有一段时间了,但是(至少现在有)一个由the documentation 支持的单行代码:

    In [4]: df
    Out[4]:
          label
    0  (a, c, e)
    1     (a, d)
    2       (b,)
    3     (d, e)
    
    In [5]: df['label'].str.join(sep='*').str.get_dummies(sep='*')
    Out[5]:
       a  b  c  d  e
    0  1  0  1  0  1
    1  1  0  0  1  0
    2  0  1  0  0  0
    3  0  0  0  1  1
    

    【讨论】:

    • +1:您先生……是某种巫师!正是我需要的.. thx :)
    • 根据我的问题,我认为df['label'].str.get_dummies(sep='*') 就足够了。我想如果字符串尚未格式化,则需要第一部分,因为 get_dummies 函数期望它们是
    • 答案已经很老了,但是我很难理解它是如何工作的。有人可以评论结构吗?我有一个类似的情况,每一行都是一个字符串列表。该解决方案就像一个魅力,但我想了解为什么....
    • 杰出的解决方案@offbyone
    【解决方案4】:

    我相信在遇到 sklearn 的 MultiLabelBinarizer 后,这个问题需要更新的答案。

    这个的用法很简单……

    # Instantiate the binarizer
    mlb = MultiLabelBinarizer()
    
    # Using OP's original data frame
    df = pd.DataFrame(data=['A', 'B', 'C', 'D', 'A*C', 'C*D'], columns=["label"])
    
    print(df)
      label
    0     A
    1     B
    2     C
    3     D
    4   A*C
    5   C*D
    
    # Convert to a list of labels
    df = df.apply(lambda x: x["label"].split("*"), axis=1)
    
    print(df)
    0       [A]
    1       [B]
    2       [C]
    3       [D]
    4    [A, C]
    5    [C, D]
    dtype: object
    
    # Transform to a binary array
    array_out = mlb.fit_transform(df)
    
    print(array_out)
    [[1 0 0 0]
     [0 1 0 0]
     [0 0 1 0]
     [0 0 0 1]
     [1 0 1 0]
     [0 0 1 1]]
    
    # Convert back to a dataframe (unnecessary step in many cases)
    df_out = pd.DataFrame(data=array_out, columns=mlb.classes_)
    
    print(df_out)
       A  B  C  D
    0  1  0  0  0
    1  0  1  0  0
    2  0  0  1  0
    3  0  0  0  1
    4  1  0  1  0
    5  0  0  1  1
    

    这也非常快,几乎没有时间(0.03 秒)跨越 1000 行和 50K 类。

    【讨论】:

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