如何将包含存储为文本和数字的值的Pandas列分隔为两个单独的列

时间:2019-07-02 11:42:35

标签: python python-3.x pandas

我有一个Pandas列,其中包含调查的结果,这些结果可以是自由文本,也可以是1-5的数字。我正在从JSON格式的API中检索这些并将它们转换为DataFrame。每行代表一个问题,参与者的回答是这样的:

Memberid | Question | Answer
       1   Q1             3
       1   Q2             2
       1   Q3         Test Text
       2   Q1             3
       2   Q2             2
       2   Q3         Test Text

具有结果的列现在将所有结果存储为字符串,因此,将结果导出为ex​​cel时,数字将存储为文本。

我的目标是为文本答案提供一个单独的列,并保留它们原来为空的字段,以便为计算结果而为文本结果和数字结果提供单独的列。

Memberid | Question | Numeric Answers | Freetext answers
       1   Q1             3
       1   Q2             2
       1   Q3                             Test Text
       2   Q1             3
       2   Q2             2
       2   Q3                             Test Text

我正在从像这样的列表中生成此df:

d = {'Memberid':memberid, 'Question':title, 'Answer':results}
df = pd.DataFrame(d)

所以我尝试的第一件事是通过以下方式将列中的数值从字符串转换为数字:

df["Answer"] = pd.to_numeric(df['Answer'], errors='ignore')

想法是,如果可行,我可以简单地执行一个for循环来检查答案列中的值是否为字符串,然后将该值移到新列中。

问题是,错误命令无法按我的预期运行。当我将其保留为ignore时,没有任何转换。当我将其更改为强制时,数字会从str转换为数字,但是自由文本答案所在的字段现在在Excel中为空。

5 个答案:

答案 0 :(得分:8)

您可以将Series.str.extract与正则表达式一起使用:

  • (\D+)将提取连续的数字
  • ?P<text>将提取连续的非数字字符
  • df.join(df.pop('Answer').str.extract('(?P<numbers>\d+)?(?P<text>\D+)?').fillna('')) 语法将命名您的匹配组-使其成为列标题。

   Memberid Question numbers       text
0         1       Q1       3           
1         1       Q2       2           
2         1       Q3          Test Text
3         2       Q1       3           
4         2       Q2       2           
5         2       Q3          Test Text

[出]

import numpy as np
import matplotlib.pyplot as plt
from scipy.spatial import distance 
center_points = []

def combinations(x,y):
    dx = 2
    dy = 2
    return x-dx,y-dy

for x in range(10):
    for y in range(10):
        center_points.append(combinations(x,y))

sample = np.random.rand(100,100)

#spatial distance 
spatial_distance = []

data = np.empty((100,100))

def ellipse(x,y):
    if (x**2+y**2/3)>300: 
        return 0
    else:
        return 1

def translate(x, y, DX, DY):
    return (x- DX, y - DY)

def rotate(m, n):
    theta = np.radians(45)
    matrix = np.array([[np.cos(theta), -np.sin(theta)], [np.sin(theta), np.cos(theta)]])
    return np.dot(matrix, (m,n))

for i in range(data.shape[0]):
    for j in range(data.shape[1]): 
        data[i][j]= ellipse(i,j)
        data[i][j]= rotate(i,j)
        for a,b in center_points: 
            data.append((translate(i,j,a,b)))
            spatial_distance.append(distance.hamming(data,sample))

答案 1 :(得分:2)

可以执行以下操作来构造2个列表(一个用于文本数据,另一个用于数字数据):

text_data = ["" if s.isdigit() else s for s in df['Question']] # "" default string
numeric_data = [s if s.isdigit() else 0 for s in df['Question']] # 0 default numeric value

答案 2 :(得分:2)

您可以执行以下操作:

import pandas as pd
df = pd.DataFrame({"Question":['Q1', 'Q2','Q3'],'Answers':['Answer1', '1','2']})
idx = df.Answers.str.isnumeric()
df['Numeric Answers'] = None
df['Freetext answers'] = ''
df.loc[~idx, 'Freetext answers'] = df.loc[~idx, 'Answers']
df.loc[idx, 'Numeric Answers'] = df.loc[idx, 'Answers']
```

答案 3 :(得分:2)

您可以使用categories=convert(r'D:\files\67cecf40-71cf-4fc4-82e1-696ca41a9fba.pdf') @app.route('/dtd/<restCategory>') def returnResult(restCategory) if restCategory in categories: DO_SOMETHING_HERE 构建Numeric Answers列,然后在该列上使用to_numeric(,errors='coerce')来构建isna一个:

FreeText Answers

它给出:

df['Numeric Answers'] = pd.to_numeric(df['Answer'], errors='coerce')
mask = df['Numeric Answers'].isna()
df.loc[mask, 'FreeText Answers'] = df.loc[mask, 'Answer']
df.drop(columns=['Answer'])

如果您不喜欢 Memberid Question Numeric Answers FreeText Answers 0 1 Q1 3.0 NaN 1 1 Q2 2.0 NaN 2 1 Q3 NaN Test Text 3 2 Q1 3.0 NaN 4 2 Q2 2.0 NaN 5 2 Q3 NaN Test Text ,可以将它们替换为空字符串:

NaN

最终获得:

df['FreeText Answers'].fillna('', inplace=True)
df['Numeric Answers'] = df['Numeric Answers'].astype(object).fillna('')

答案 4 :(得分:2)

希望这能回答您的问题。我使用了字符串数字方法   将数字与文本分开。然后,您可以应用pd.numeric进行转换   数字列

    import pandas as pd
    import numpy as np
    import string   

     a={
        'Memberid':[1,1,1,2,2,2],
        'Question':['Q1','Q2','Q3','Q1','Q2','Q3'],
        'Answer':['3','2','Test Text','3','2','Test Text']
      }

    df = pd.DataFrame.from_dict(a)
    digits = list(string.digits)   
    df = df.assign(Numeric_Answers= np.where(df['Answer'].isin(digits),                          
                                             df['Answer'],
                                             np.nan
                                            ),

                   FreeText =       np.where(df['Answer'].isin(digits),
                                             np.nan,
                                             df['Answer']
                                           )
                  )

        Memberid    Question    Answer  Numeric_Answers     FreeText
    0       1        Q1           3          3                 NaN
    1       1        Q2           2          2                 NaN
    2       1        Q3        Test Text    NaN             Test Text
    3       2        Q1           3          3                 NaN
    4       2        Q2           2          2                 NaN
    5       2        Q3        Test Text    NaN             Test Text