【问题标题】:Data munging in pandaspandas 中的数据处理
【发布时间】:2016-02-14 20:25:26
【问题描述】:

我有一个 CSV 文件,其中的行如下所示:

ID,98.4,100M,55M,65M,75M,100M,75M,65M,100M,98M,100M,100M,92M,0#,0N#,

我可以阅读它

#!/usr/bin/env python

import pandas as pd
import sys

filename = sys.argv[1]
df = pd.read_csv(filename)

给定一个特定的列,我想按 ID 拆分行,然后输出每个 ID 的平均值和标准差。

我的第一个问题是,如何从数字中删除所有非数字部分,例如“100M”和“0N#”,它们应该分别是 100 和 0。

我也尝试过遍历相关的标题并使用

df[header].replace(regex=True,inplace=True,to_replace=r'\D',value=r'')

正如Pandas DataFrame: remove unwanted parts from strings in a column 中所建议的那样。

但是,这会将 98.4 更改为 984。

【问题讨论】:

  • @Evert 添加了一个编辑以显示我需要如何处理小数点。
  • 我列出的重复项建议使用rstrip,以及您要删除的字符。所以 ...rstrip('MN#') 应该可以很好地为您的输入工作,使用副本中建议的 lambda(当然,您可以省略 lstrip 部分)。
  • @Evert 问题是 MN# 不是唯一的非数字字符。我想我也必须做 lstrip to 吗?
  • @Evert 另外,我在标题上的循环也不起作用。 for header in list(df)[9:-3]: 给我列而不是标题。这样做的正确方法是什么?

标签: python pandas dataframe data-manipulation data-munging


【解决方案1】:

我的第一个问题是,如何从数字中删除所有非数字部分,例如“100M”和“0N#”,它们应该分别是 100 和 0。

import re
df = pd.read_csv(yourfile, header=None)
df.columns = ['ID'] + list(df.columns)[1:]
df = df.stack().apply(lambda v: re.sub('[^0-9]','', v) 
                 if isinstance(v, str) else v).astype(float).unstack()
df.groupby('ID').agg(['std', 'mean'])

这里.stack() 将数据帧转换为系列,.apply() 为每个值调用 lambda,re.sub() 删除所有非数字字符,.astype() 转换为数字,unstack() 将系列转换回数据框。这对整数和浮点数同样适用。

给定一个特定的列,我想按 ID 拆分行,然后输出每个 ID 的平均值和标准差。

 # for all columns
 df.groupby('ID').agg(['std', 'mean'])
 # for specific column
 df.groupby('ID')['<colname>'].agg(['std', 'mean'])

这是示例中使用的数据:

from StringIO import StringIO
s="""
1,98.4,100M,55M,65M,75M,100M,75M,65M,100M,98M,100M,100M,92M,0#,0N#,
1,98.4,100M,55M,65M,75M,100M,75M,65M,100M,98M,100M,100M,92M,0#,0N#,
2,98.4,100M,55M,65M,75M,100M,75M,65M,100M,98M,100M,100M,92M,0#,0N#,
2,98.4,100M,55M,65M,75M,100M,75M,65M,100M,98M,100M,100M,92M,0#,0N#,
"""
yourfile = StringIO(s)

【讨论】:

    【解决方案2】:

    使用str.extract:

    In [356]:
    import io
    import pandas as pd
    t="""ID,98.4,100M,55M,65M,75M,100M,75M,65M,100M,98M,100M,100M,92M,0#,0N#"""
    df = pd.read_csv(io.StringIO(t), header=None)
    df
    
    Out[356]:
       0     1     2    3    4    5     6    7    8     9    10    11    12   13  \
    0  ID  98.4  100M  55M  65M  75M  100M  75M  65M  100M  98M  100M  100M  92M   
    
       14   15  
    0  0#  0N#  
    
    In [357]:
    for col in df.columns[2:]:
        df[col] = df[col].str.extract(r'(\d+)').astype(int)
    df
    
    Out[357]:
       0     1    2   3   4   5    6   7   8    9   10   11   12  13  14  15
    0  ID  98.4  100  55  65  75  100  75  65  100  98  100  100  92   0   0
    

    如果你有浮点数,那么你可以使用以下正则表达式:

    In [379]:
    t="""ID,98.4,100.50M,55.234M,65M,75M,100M,75M,65M,100M,98M,100M,100M,92M,0#,0N#"""
    df = pd.read_csv(io.StringIO(t), header=None)
    df
    
    Out[379]:
       0     1        2        3    4    5     6    7    8     9    10    11  \
    0  ID  98.4  100.50M  55.234M  65M  75M  100M  75M  65M  100M  98M  100M   
    
         12   13  14   15  
    0  100M  92M  0#  0N#  
    
    In [380]:    
    for col in df.columns[2:]:
        df[col] = df[col].str.extract(r'(\d+\.?\d+)').astype(np.float)
    df
    
    Out[380]:
       0     1      2       3   4   5    6   7   8    9   10   11   12  13  14  15
    0  ID  98.4  100.5  55.234  65  75  100  75  65  100  98  100  100  92 NaN NaN
    

    所以(\d+\.?\d+) 查找包含\d+ 1 位或更多位且\.? 可选小数点和\d+ 小数点后1 位或更多位的组

    编辑

    OK 编辑了我的正则表达式模式:

    In [408]:
    t="""Name,97.7,0A,0A,65M,0A,100M,5M,75M,100M,90M,90M,99M,90M,0#,0N#"""
    df = pd.read_csv(io.StringIO(t), header=None)
    df
    
    Out[408]:
         0     1   2   3    4   5     6   7    8     9    10   11   12   13  14  \
    0  Name  97.7  0A  0A  65M  0A  100M  5M  75M  100M  90M  90M  99M  90M  0#   
    
        15  
    0  0N#  
    
    In [409]:    
    for col in df.columns[2:]:
        df[col] = df[col].str.extract(r'(\d+\.*\d*)').astype(np.float)
    df
    
    Out[409]:
         0     1   2   3   4   5    6   7   8    9   10  11  12  13  14  15
    0  Name  97.7   0   0  65   0  100   5  75  100  90  90  99  90   0   0
    

    【讨论】:

    • df = pd.read_csv(io.StringIO(t), header=None) TypeError: initial_value must be unicode or None, not str
    • 忽略io.StringIO 位,这只是我在您的情况下将您的文本作为文件对象读取df=pd.read_csv(filename) 很好
    • 如果这是整个文件 "Name",97.7,0A,0A,65M,0A,100M,5M,75M,100M,90M,90M,99M,90M,0#,0N#, " 你的代码给了我 "0 Name NaN NaN NaN 65 NaN 100 NaN 75 100 90 90 99 90 NaN NaN NaN"
    • 编辑后的版本更好,给0 Name NaN 0 0 65 0 100 5 75 100 90 90 99 90 0 0 NaN。这仍然会在开始时杀死 97.7。
    • 我没看到,你能把原始输入数据和代码发布到你的问题中
    猜你喜欢
    • 2020-06-13
    • 2017-02-10
    • 2017-02-17
    • 2020-05-31
    • 2015-12-10
    • 2016-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多