Pandas - 在一列上应用函数并返回一个新列

时间:2016-02-18 11:40:29

标签: pandas

我有一个函数findFullPath,它接受​​一个文件的字符串,并使用完整路径列表查找该文件的完整路径。例如;

    >>> i = 4000
    >>> serisuid = candidates.iloc[i].seriesuid
    >>> fullPath = findFullPath(serisuid,fullPaths)
    >>> print(serisuid)
    >>> print(fullPath)

    1.3.6.1.4.1.14519.5.2.1.6279.6001.100684836163890911914061745866
    /home/msmith/luna16/subset1/1.3.6.1.4.1.14519.5.2.1.6279.6001.100684836163890911914061745866.raw

我正在尝试将此函数应用于完整列候选[“seriesuid”]并使用类似下面的内容返回带有完整路径的新列,但到目前为止它不成功;

>>> candidates["seriesuidFullPaths"] = candidates[["seriesuid"]].apply(findFullPath,args=(fullPaths,),axis=1)

[编辑]

抱歉有点含糊不清。所以我的功能是

def findFullPath(seriesuid,fullPaths):
    fullPath = [s.replace(".mhd",".raw") for s in fullPaths if serisuid in s][0]
    return fullPath

在我通过顶部给出的案例代码完美地工作,但是当我在系列中应用它时会产生不正确的完整文件路径。此外,我得到了一个复制错误;

A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

但我认为我正在编辑实际的数据框,所以我有点困惑。

[实施例]

>>> candidates.head()

                                                          seriesuid  coordX  \
0  1.3.6.1.4.1.14519.5.2.1.6279.6001.100225287222365663678666836860  -56.08   
1  1.3.6.1.4.1.14519.5.2.1.6279.6001.100225287222365663678666836860   53.21   
2  1.3.6.1.4.1.14519.5.2.1.6279.6001.100225287222365663678666836860  103.66   
3  1.3.6.1.4.1.14519.5.2.1.6279.6001.100225287222365663678666836860  -33.66   
4  1.3.6.1.4.1.14519.5.2.1.6279.6001.100225287222365663678666836860  -32.25   

   coordY  coordZ  class  
0  -67.85 -311.92      0  
1 -244.41 -245.17      0  
2 -121.80 -286.62      0  
3  -72.75 -308.41      0  
4  -85.36 -362.51      0  

我刚刚更新了fullPaths以仅包含.raw个文件。

>>> fullPaths = [path for path in fullPaths if ".raw" in path]
>>> fullPaths[:5] 
['/home/msmith/luna16/subset4/1.3.6.1.4.1.14519.5.2.1.6279.6001.142154819868944114554521645782.raw',
     '/home/msmith/luna16/subset4/1.3.6.1.4.1.14519.5.2.1.6279.6001.211071908915618528829547301883.raw',
     '/home/msmith/luna16/subset4/1.3.6.1.4.1.14519.5.2.1.6279.6001.390009458146468860187238398197.raw',
     '/home/msmith/luna16/subset4/1.3.6.1.4.1.14519.5.2.1.6279.6001.463214953282361219537913355115.raw',
     '/home/msmith/luna16/subset4/1.3.6.1.4.1.14519.5.2.1.6279.6001.252358625003143649770119512644.raw']

我想用相关的.raw文件路径替换候选中的每个seriesuid。希望这可以解决它。

2 个答案:

答案 0 :(得分:1)

此错误:

A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

通常,当您在DataFrame的切片上应用函数时会发生这种情况。

你摆脱这个错误的一种方法是:

candidates = df.loc[<Your condition>].copy()

其中df是您最初创建的源DataFrame。

然后,如果它是正确的,它应该工作:

candidates["seriesuidFullPaths"] = candidates[["seriesuid"]].apply(findFullPath,args=(fullPaths,),axis=1)

答案 1 :(得分:1)

您可以尝试从列表DataFrame创建新p fullPath,将seriesuid提取到新列seriesuid,然后merge将其提取{ {1}}列DataFrame的候选人。

我更改了列表seriesuid中的第一个和最后一个项目以进行测试:

fullPath
   
print candidates
                                           seriesuid  coordX  coordY  coordZ  \
0  9.3.6.1.4.1.14519.5.2.1.6279.6001.100225287222...  -56.08  -67.85 -311.92   
1  1.3.6.1.4.1.14519.5.2.1.6279.6001.100225287222...   53.21 -244.41 -245.17   
2  1.3.6.1.4.1.14519.5.2.1.6279.6001.100225287222...  103.66 -121.80 -286.62   
3  1.3.6.1.4.1.14519.5.2.1.6279.6001.100225287222...  -33.66  -72.75 -308.41   
4  1.3.6.1.4.1.14519.5.2.1.6279.6001.100225287222...  -32.25  -85.36 -362.51   

   class  
0      0  
1      0  
2      0  
3      0  
4      0  
fullPath = ['/home/msmith/luna16/subset4/9.3.6.1.4.1.14519.5.2.1.6279.6001.100225287222365663678666836860.raw',
     '/home/msmith/luna16/subset4/1.3.6.1.4.1.14519.5.2.1.6279.6001.211071908915618528829547301883.raw',
     '/home/msmith/luna16/subset4/1.3.6.1.4.1.14519.5.2.1.6279.6001.390009458146468860187238398197.raw',
     '/home/msmith/luna16/subset4/1.3.6.1.4.1.14519.5.2.1.6279.6001.463214953282361219537913355115.raw',
     '/home/msmith/luna16/subset4/9.3.6.1.4.1.14519.5.2.1.6279.6001.100225287222365663678666836860.raw']

p = pd.DataFrame(fullPath, columns=['paths'])
p["paths"] = p["paths"].str.replace(".raw","")
p['seriesuid'] = p['paths'].str.split('/').str[5]
print p
                                               paths  \
0  /home/msmith/luna16/subset4/9.3.6.1.4.1.14519....   
1  /home/msmith/luna16/subset4/1.3.6.1.4.1.14519....   
2  /home/msmith/luna16/subset4/1.3.6.1.4.1.14519....   
3  /home/msmith/luna16/subset4/1.3.6.1.4.1.14519....   
4  /home/msmith/luna16/subset4/9.3.6.1.4.1.14519....   

                                           seriesuid  
0  9.3.6.1.4.1.14519.5.2.1.6279.6001.100225287222...  
1  1.3.6.1.4.1.14519.5.2.1.6279.6001.211071908915...  
2  1.3.6.1.4.1.14519.5.2.1.6279.6001.390009458146...  
3  1.3.6.1.4.1.14519.5.2.1.6279.6001.463214953282...  
4  9.3.6.1.4.1.14519.5.2.1.6279.6001.100225287222...  

如果列表print pd.merge(candidates, p, on=['seriesuid']) seriesuid coordX coordY coordZ \ 0 9.3.6.1.4.1.14519.5.2.1.6279.6001.100225287222... -56.08 -67.85 -311.92 1 9.3.6.1.4.1.14519.5.2.1.6279.6001.100225287222... -56.08 -67.85 -311.92 class paths 0 0 /home/msmith/luna16/subset4/9.3.6.1.4.1.14519.... 1 0 /home/msmith/luna16/subset4/9.3.6.1.4.1.14519.... 中的目录长度不同,您可以使用:

fullPath
fullPath = ['/home/msmith/luna16/subset4/9.3.6.1.4.1.14519.5.2.1.6279.6001.100225287222365663678666836860.raw',
     '/home/msmith/luna16/subset4/1.3.6.1.4.1.14519.5.2.1.6279.6001.211071908915618528829547301883.raw',
     '/msmith/luna16/subset4/1.3.6.1.4.1.14519.5.2.1.6279.6001.390009458146468860187238398197.raw',
     '/home/msmith/luna16/subset4/1.3.6.1.4.1.14519.5.2.1.6279.6001.463214953282361219537913355115.raw',
     '/home/msmith/luna16/subset4/9.3.6.1.4.1.14519.5.2.1.6279.6001.100225287222365663678666836860.raw']

p = pd.DataFrame(fullPath, columns=['paths'])
#replace .raw to empty string
p["paths"] = p["paths"].str.replace(".raw","")
#find last string splitted by / and get it to column seriesuid
p[['tmp','seriesuid']] = p['paths'].str.rsplit('/', expand=True, n=1)
#drop unnecessary column tmp
p = p.drop(['tmp'], axis=1)
print p
                                               paths  \
0  /home/msmith/luna16/subset4/9.3.6.1.4.1.14519....   
1  /home/msmith/luna16/subset4/1.3.6.1.4.1.14519....   
2  /msmith/luna16/subset4/1.3.6.1.4.1.14519.5.2.1...   
3  /home/msmith/luna16/subset4/1.3.6.1.4.1.14519....   
4  /home/msmith/luna16/subset4/9.3.6.1.4.1.14519....   

                                           seriesuid  
0  9.3.6.1.4.1.14519.5.2.1.6279.6001.100225287222...  
1  1.3.6.1.4.1.14519.5.2.1.6279.6001.211071908915...  
2  1.3.6.1.4.1.14519.5.2.1.6279.6001.390009458146...  
3  1.3.6.1.4.1.14519.5.2.1.6279.6001.463214953282...  
4  9.3.6.1.4.1.14519.5.2.1.6279.6001.100225287222...