我有3个数据框,可以通过下面的代码生成
df1= pd.DataFrame({'person_id':[1,2,3],'gender': ['Male','Female','Not disclosed'],'ethn': ['Chinese','Indian','European']})
df2= pd.DataFrame({'pers_id':[4,5,6],'gen': ['Male','Female','Not disclosed'],'ethnicity': ['Chinese','Indian','European']})
df3= pd.DataFrame({'son_id':[7,8,9],'sex': ['Male','Female','Not disclosed'],'ethnici': ['Chinese','Indian','European']})
我想做两件事
a)将所有这三个数据框附加到一个大的result
数据框中
当我尝试使用以下代码进行此操作时,输出结果与预期不符
df1.append(df2)
因此,要解决此问题,我了解我们必须重命名导致以下目标b的列名称
b)以优雅的方式将这n个数据框的列重命名为统一
请注意,我可能会实时获得一个具有不同列名的数据框,这些列名我可能事先都不知道,但是它们中的值始终属于列Ethnicity
,Gender
和{ {1}}。但请注意,还有其他几列,例如Person_id
,Age
,Date
等
当前,我是通过使用以下代码手动读取列名来实现的
bp reading
无论原始列值如何,如何将所有数据框的列名设置为相同(df2.columns
df2.rename(columns={ethnicity:'ethn',gender = 'gen',person_id='pers_id},
inplace=True)
,gender
,ethnicity
等)
答案 0 :(得分:2)
根据pandas
documentation,您可以执行以下操作以创建映射:
df2.rename(columns={column1:'ethn', column2:'gen', column3:'pers_id'}, inplace=True)
现在,您清楚地声明必须执行此运行时。如果您知道列数及其相应位置不会改变,则可以使用df2.columns()
收集实际的列名,这将输出如下内容:
['ethnicity', 'gender', 'person_id']
此时,您可以按以下方式创建映射:
final_columns = ['ethn', 'gen', 'pers_id']
previous_columns = df2.columns()
mapping = {previous_columns[i]: final_columns[i] for i in range(3)} # 3 is arbitrary.
然后打电话
df2.rename(mapping, inplace=True)
答案 1 :(得分:1)
如果您不知道列的顺序,可以尝试模糊匹配方法。模糊匹配将为您提供介于0到100之间的相似度/相似度值。因此,您可以确定相似度阈值,然后替换与所需列名相似的列。这是我的方法:
import pandas as pd
from fuzzywuzzy import process
df1= pd.DataFrame({'person_id':[1,2,3],'gender': ['Male','Female','Not disclosed'],'ethn': ['Chinese','Indian','European']})
df2= pd.DataFrame({'pers_id':[4,5,6],'gen': ['Male','Female','Not disclosed'],'ethnicity': ['Chinese','Indian','European']})
df3= pd.DataFrame({'son_id':[7,8,9],'sex': ['Male','Female','Not disclosed'],'ethnici': ['Chinese','Indian','European']})
dataFrames = [df1, df2, df3]
for dataFrame in dataFrames:
for i, column in enumerate(list(dataFrame.columns)):
if dataFrame.columns[i] == "sex":
dataFrame.rename(columns={ dataFrame.columns[i]: "gender" }, inplace = True)
colsToFix = ["person_id", "gender", "ethnicity"]
replaceThreshold = 75
ratiosPerDf = list()
for i, dataFrame in enumerate(dataFrames):
ratioDict = dict()
for column in colsToFix:
ratios = process.extract(column, list(dataFrame.columns))
ratioDict[column] = ratios
ratiosPerDf.append(ratioDict)
for i, dfRatio in enumerate(ratiosPerDf):
for column in colsToFix:
bestMatching = ("", 0)
for item in dfRatio[column]:
if item[1] >= replaceThreshold and item[1] > bestMatching[1]:
bestMatching = item
if not bestMatching[1] < replaceThreshold:
print("Column : {} Best matching : {}".format(column, bestMatching[0]))
dataFrames[i].rename(columns={ bestMatching[0] : column }, inplace = True)
答案 2 :(得分:0)
如https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.rename.html所述,您可以将多个列名一起传递,这些列名可以指向所需的相同最终列名。因此,最好的方法是收集所有列名,然后根据某种算法或手动将它们映射到所需的通用名,然后运行rename命令。
该算法既可以使用名称的相似性(使用TF-IDF),也可以使用这些列的值相似性。