【问题标题】:Pandas: Separate column containing semicolon into multiple columns based on the valuesPandas:根据值将包含分号的列分成多列
【发布时间】:2019-09-30 02:23:45
【问题描述】:

我在ddata.csv中的数据如下:

col1,col2,col3,col4
A,10,a;b;c, 20
B,30,d;a;b,40
C,50,g;h;a,60

我想根据它们的值将 col3 分成多个列。在其他方面,我希望我的最终数据看起来像

col1, col2, name_a, name_b, name_c, name_d, name_g, name_h, col4
A,    10,   a,      b,      c,      NULL,   NULL,   NULL,   20
B,    30,   a,      b,      NULL,   d,      NULL,   NULL,   40
C,    50,   a,      NULL,   NULL,   NULL,   g,      h,      60

我的代码,目前引用自 answer,不完整:

import pandas as pd

import string
L = list(string.ascii_lowercase)

names = dict(zip(range(len(L)), ['name_' + x for x in  L]))
df = pd.read_csv('ddata.csv')
df2 = df['col3'].str.split(';', expand=True).rename(columns=names)

列名'a','b','c' ...是随机取的,与实际数据a,b,c无关。

现在,我的代码可以将 'col3' 分成三列,如下所示:

name_a name_b name_c
a      b      c
d      e      f
g      h      i

但是,应该是这样的 name_a, name_b, name_c, name_d, name_g, name_h a, b, c, 空, 空, 空 a, b, 空, d, 空, 空 一、空、空、空、g、h

最后,我只需要用这些多列替换 col3。

【问题讨论】:

  • @razdi 我的代码只是将第 3 列拆分为 3 列 - name_a、name_b 和 name_c。但是,列 name_a 应该只包含 'a' 而不是 'd' 或 'h'。我需要根据它们的值来分隔列。

标签: python pandas csv dataframe


【解决方案1】:

使用Series.str.get_dummies:

print (df['col3'].str.get_dummies(';'))
   a  b  c  d  g  h
0  1  1  1  0  0  0
1  1  1  0  1  0  0
2  1  0  0  0  1  1

对于从原始使用 DataFrame.pop 中提取列 col3,通过 numpy 中的列名称的多个值创建新的 DataFrame,用 DataFrame.whereDataFrame.add_prefix 替换空字符串替换新列名称.

pos = df.columns.get_loc('col3')

df2 = df.pop('col3').str.get_dummies(';').astype(bool)
df2 = (pd.DataFrame(df2.values * df2.columns.values[ None, :], 
                    columns=df2.columns,
                    index=df2.index)
         .where(df2)
         .add_prefix('name_'))

最后通过iloc加入所有按位置过滤的DataFramesconcat加入:

df = pd.concat([df.iloc[:, :pos], df2, df.iloc[:, pos:]], axis=1)
print (df)
  col1  col2 name_a name_b name_c name_d name_g name_h  col4
0    A    10      a      b      c    NaN    NaN    NaN    20
1    B    30      a      b    NaN      d    NaN    NaN    40
2    C    50      a    NaN    NaN    NaN      g      h    60

【讨论】:

  • 非常感谢。我现在如何用这些多列替换 col3 ?不打扰其余的列/行?
【解决方案2】:

@jezrael 解决方案非常好。直到现在我才知道str.get_dummies

我使用stackpivot_tablenp.wherepd.concat 提出了解决方案

df1 = df.col3.str.split(';', expand=True).stack().reset_index(level=0)
df2 = pd.pivot_table(df1, index='level_0', columns=df1[0], aggfunc=len)

Out[1658]:
0          a    b    c    d    g    h
level_0
0        1.0  1.0  1.0  NaN  NaN  NaN
1        1.0  1.0  NaN  1.0  NaN  NaN
2        1.0  NaN  NaN  NaN  1.0  1.0

接下来,使用np.where 用列名填充1.0,找到col3 的索引并使用pd.concat 构造最终的df

df2[:] = np.where(df2.isna(), np.nan, df2.columns)
i = df.columns.tolist().index('col3')
pd.concat([df.iloc[:,:i], df2.add_prefix('name_'), df.iloc[:,i+1:]], axis=1)

Out[1667]:
  col1  col2 name_a name_b name_c name_d name_g name_h  col4
0    A    10      a      b      c    NaN    NaN    NaN    20
1    B    30      a      b    NaN      d    NaN    NaN    40
2    C    50      a    NaN    NaN    NaN      g      h    60

【讨论】:

  • 我也不知道 str.get_dummies 把戏。杰兹瑞尔是个天才!
猜你喜欢
  • 2018-04-28
  • 2023-02-17
  • 1970-01-01
  • 2015-09-08
  • 2018-02-27
  • 1970-01-01
  • 2021-08-31
  • 2018-11-11
  • 1970-01-01
相关资源
最近更新 更多