熊猫数据框中的按单元计算

时间:2020-03-05 16:40:55

标签: python pandas dataframe

我确信对Python中的数据帧如何工作根本缺乏了解。我敢肯定,这是一个简单的问题,但是我到处都是,找不到很好的解释。我试图理解为什么有时数据帧计算似乎是逐行(或逐个单元格)地运行,而有时似乎是针对整个列运行的。例如:

data = {'Name':['49-037-23094', '49-029-21476', '49-029-20812', '49-041-21318'], 'Depth':[20, 21, 7, 18]} 
df = pd.DataFrame(data) 
df

哪个给出:

           Name  Depth
0  49-037-23094     20
1  49-029-21476     21
2  49-029-20812      7
3  49-041-21318     18

现在我知道我可以做到:

df['DepthDouble']=df['Depth']*2

并获取:

           Name  Depth  DepthDouble
0  49-037-23094     20           40
1  49-029-21476     21           42
2  49-029-20812      7           14
3  49-041-21318     18           36

这是我期望的。但这并不总是有效,我试图理解原因。例如,我正在尝试运行以下代码来修改名称:

df['newName']=''.join(re.findall('\d',str(df['Name'])))

给出:

           Name  Depth  DepthDouble  \
0  49-037-23094     20           40   
1  49-029-21476     21           42   
2  49-029-20812      7           14   
3  49-041-21318     18           36   

                                        newName  
0  04903723094149029214762490292081234904121318  
1  04903723094149029214762490292081234904121318  
2  04903723094149029214762490292081234904121318  
3  04903723094149029214762490292081234904121318  

因此,它将我的名称列中的所有值取走,删除破折号并将其连接起来。当然,我希望它是一个与原始“名称”列完全相同的新名称列,但没有破折号。

那么,有人可以帮助我了解我在这里做错了什么吗?我不明白为什么有时一列的Dataframe计算是逐行完成的(例如Depth Doubled列),而Python有时似乎会占用整个列中的所有值并运行计算(例如newName列)。

解决这个问题的方法肯定不是通过对df中的每个索引进行循环来强制它针对给定列的每一行单独运行吗?

2 个答案:

答案 0 :(得分:0)

如果您要查找的输出是:

Name    Depth   newName
0   49-037-23094    20  4903723094
1   49-029-21476    21  4902921476
2   49-029-20812    7   4902920812
3   49-041-21318    18  4904121318

获得此信息的方法是:

df['newName']=df['Name'].map(lambda name: ''.join(re.findall('\d', name)))

map类似于apply,但专门用于Series对象。由于仅适用于“名称”列,因此您要对“系列”进行操作。

如果lambda部分令人困惑,则等效的书写方式是:

def find_digits(name):
    return ''.join(re.findall('\d', name))

df['newName']=df['Name'].map(find_digits)

传统的for循环中的等效操作是:

newNameSeries = pd.Series(name='newName')
for name in df['Name']:
    newNameSeries = newNameSeries.append(pd.Series(''.join(re.findall('\d', name))), ignore_index=True)

pd.concat([df, newNameSeries], axis=1).rename(columns={0:'newName'})

虽然可能有一种更简洁的循环方法,但您可以看到第一种方法与尝试使用for循环相比要简单得多。它也更快。正如您已经指出的那样,使用熊猫时请避免for循环。

答案 1 :(得分:0)

问题在于,使用str(df['Name'])会将DataFrame的整个Name列转换为一个字符串。相反,您要做的是使用熊猫自己的字符串方法之一,该方法将应用于列的每个元素。

例如,您可以对字符串使用pandas的replace方法:

import pandas as pd
data = {'Name':['49-037-23094', '49-029-21476', '49-029-20812', '49-041-21318'],    'Depth':[20, 21, 7, 18]} 
df = pd.DataFrame(data) 

df['newName'] = df['Name'].str.replace('-', '')