我确信对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中的每个索引进行循环来强制它针对给定列的每一行单独运行吗?
答案 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('-', '')