【问题标题】:Pandas dataframe column headers to labels for data熊猫数据框列标题到数据标签
【发布时间】:2020-01-11 09:37:35
【问题描述】:

总结: 我的代码输出为我提供了以下格式的数据框。数据框的列标题是Content 列中文本的标签。这些标签将在下一步中用作多标签分类器的训练数据。这是一个更大的实际数据的 sn-p。

由于它们是列标题,因此无法将它们映射到它们作为标签的文本。

Content  A  B  C  D  E
    zxy  1  2     1   
    wvu  1     2  1   
    tsr  1  2        2
    qpo     1  1  1   
    nml        2  2   
    kji  1     1     2
    hgf        1     2
    edc  1  2     1              

更新:将 df 转换为 csv 显示空单元格为空白('' vs ' '):

其中Content是文本所在的列,ABCDE是需要转为标签的列标题。只有带有 1 或 2 的列是相关的。具有空单元格的列不相关,因此不需要转换为标签。

更新:经过一番挖掘,也许数字可能不是整数,而是字符串。

我知道在将文本+标签输入分类器进行处理时,两个数组的长度需要相等,否则不被接受为有效输入。

有没有办法可以将列标题转换为 DF 中 Content 中文本的标签?

预期输出:

>>Content  A  B  C  D  E     Labels
0   zxy    1  2     1        A, B, D  
1   wvu    1     2  1        A, C, D
2   tsr    1  2        2     A, B, E
3   qpo       1  1  1        B, C, D
4   nml          2  2        C, D    
5   kji    1     1     2     A, C, E
6   hgf          1     2     C, E
7   edc    1  2     1        A, B, D   

【问题讨论】:

  • 你有链接或 git repo 我可以看到实际数据吗?
  • 似乎空白处是空格' '
  • 我可以从那张截图中看到,与玩具数据相比,数据有所不同。假设是,只有Content 列有实际文本,而其他列只有空白或数字。看起来很多列都有文字,这可以解释为什么没有任何效果。
  • 是的,例如s=df.loc[:,'A':]A: 表示从A 向右的所有列,第一个: 表示所有行。真实数据中的列名是否不同?
  • 嗯,这需要一些努力。欢呼!祝你好运。

标签: python python-3.x pandas csv dataframe


【解决方案1】:

完整解决方案:

# first: clear all whitespace before and after a char, fine for all columns
for col in df.columns:
    df[col] = df[col].str.strip()

# fill na with 0
df.fillna(0, inplace=True)

# replace '' with 0
df.replace('', 0, inplace=True)

# convert to int, this must only be done on the specific columns with the numeric data
# this list is the column names as you've presented them, if they are different in the real data,
# replace them
for col in ['A', 'B', 'C', 'D', 'E']:
    df = df.astype({col: 'int16'})

print(df.info())

# you should end up with something like this.
"""
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 8 entries, 0 to 7
Data columns (total 6 columns):
Content    8 non-null object
A          8 non-null int16
B          8 non-null int16
C          8 non-null int16
D          8 non-null int16
E          8 non-null int16
dtypes: int16(5), object(1)
memory usage: 272.0+ bytes
"""

我们可以做dot,注意这里,我把空白当作np.nan,如果你的数据中确实是空白,请更改最后一行

# make certain the label names match the appropriate columns 
s=df.loc[:, ['A', 'B', 'C', 'D', 'E']]  
# or
s=df.loc[:,'A':]

df['Labels']=(s>0).dot(s.columns+',').str[:-1]  # column A:E need to be numeric, not str
# df['Labels']=(~s.isin(['']).dot(s.columns+',').str[:-1]

【讨论】:

  • 使用 df.astype 将 A:E 转换为 int
  • 我将其包含在答案中。或者,df = df.astype({'A': 'int16', 'B': 'int16', 'C': 'int16', 'D': 'int16', 'E': 'int16'})
  • 尝试import numpy as np如果你没有导入numpy,然后df.fillna(np.nan, inplace=True),然后再次尝试使用astype。另外,不要尝试将实际字符串(例如字母)转换为int
  • @jottbe 实际上,我正在与 OP 进行对话,试图解决他的问题,因为所有解决方案都不起作用。
  • @mvx 我真的不知道还能尝试什么。我们所做的一切都适用于玩具数据集,但不适用于真实数据集。在这一点上,如果没有真正看到真实数据,我不知道还能尝试什么,因为这才是真正的问题所在。
【解决方案2】:

这是使用np.wheregroupby 的另一种方式:

r, c = np.where(df>0)

df['Labels'] = pd.Series(df.columns[c], index=df.index[r]).groupby(level=[0, 1]).agg(', '.join)

输出:

       A  B  C  D  E   Labels
0 zxy  1  2  0  1  0  A, B, D
1 wvu  1  0  2  1  0  A, C, D
2 tsr  1  2  0  0  2  A, B, E
3 qpo  0  1  1  1  0  B, C, D
4 nml  0  0  2  2  0     C, D
5 kji  1  0  1  0  2  A, C, E
6 hgf  0  0  1  0  2     C, E
7 edc  1  2  0  1  0  A, B, D

【讨论】:

  • 第一行代码我得到TypeError: '&gt;' not supported between instances of 'str' and 'int
  • 在索引中移动数据帧的所有字符串列。
【解决方案3】:

你也可以这样做:

# melt the two dimensional representation to
# a more or less onedimensional representation
df_flat= df.melt(id_vars=['Content'])
# filter out all rows which belong to empty cells
# the following is a fail-safe method, that should
# work for all datatypes you might encouter in your
# columns
df_flat= df_flat[~df_flat['value'].isna() & df_flat['value'] != 0]
df_flat= df_flat[~df_flat['value'].astype('str').str.strip().isin(['', 'nan'])]
# join the variables used per original row
df_flat.groupby(['Content']).agg({'variable': lambda ser: ', '.join(ser)})

输出如下所示:

            variable
idx Content         
0   zxy      A, B, D
1   wvu      A, C, D
2   tsr      A, B, E
3   qpo      B, C, D
4   nml         C, D
5   kji      A, C, E
6   hgf         C, E
7   edc      A, B, D

给定以下输入数据:

import pandas as pd
import io

raw="""idx Content  A  B  C  D  E          
0   zxy      1  2     1                    
1   wvu      1     2  1                  
2   tsr      1  2        2               
3   qpo         1  1  1                  
4   nml            2  2                      
5   kji      1     1     2               
6   hgf            1     2               
7   edc      1  2     1           """

df= pd.read_fwf(io.StringIO(raw))
df.drop(['idx'], axis='columns', inplace=True)

编辑:我刚刚在阅读后删除了'idx',以创建类似于原始数据帧中的结构,并添加了一些适用于不同数据类型的故障安全代码(融化下方的两行-方法)。如果对缺失值的实际表示方式有更多了解,则可以简化代码。

【讨论】:

  • 我没有名为idx 的列,它只是数据框中的默认编号。我尝试在代码中删除此命令并使用它,但输出显示了您编写的 variable 列中所有列标题的列表 - 而不仅仅是适用的列标题
  • @mvx,idx 可能是原始数据帧的索引,它在您提供的输出中。如果您没有将其作为列,只需从meltgroupby 中删除“idx”,它就会以相同的方式工作。
  • 顺便说一句。我根据您问题中的数据构建了数据框,即“给定以下输入数据”的部分。我敢肯定,提出答案的前人也这样做了,但他们没有添加代码来获取他们在答案中提供的输出的测试数据。但是,如果您让它在您的数据框上运行,我相信它会起作用,如果您的数据框没有根本不同,但在这种情况下,最好更改您问题中的描述。
  • 如果它使用您的代码显示所有列标题,那么空单元格似乎被转换为空字符串而不是 NaN 在这种情况下,您只需像上面一样更改df_flat= df_flat[~df_flat['value'].isna()] 行编辑。
  • 我收到AttributeError: 'Series' object has no attribute 'strip'
猜你喜欢
  • 2018-11-06
  • 2013-02-01
  • 2016-08-09
  • 2018-10-09
  • 2021-08-23
  • 2019-03-05
  • 2020-04-27
  • 2020-06-03
  • 2013-07-30
相关资源
最近更新 更多