追加具有不同列名的数据框-Pandas

时间:2019-07-29 09:33:23

标签: python python-3.x pandas python-2.7 dataframe

我有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)

enter image description here

因此,要解决此问题,我了解我们必须重命名导致以下目标b的列名称

b)以优雅的方式将这n个数据框的列重命名为统一

请注意,我可能会实时获得一个具有不同列名的数据框,这些列名我可能事先都不知道,但是它们中的值始终属于列EthnicityGender和{ {1}}。但请注意,还有其他几列,例如Person_idAgeDate

当前,我是通过使用以下代码手动读取列名来实现的

bp reading

无论原始列值如何,如何将所有数据框的列名设置为相同(df2.columns df2.rename(columns={ethnicity:'ethn',gender = 'gen',person_id='pers_id}, inplace=True) genderethnicity等)

3 个答案:

答案 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),也可以使用这些列的值相似性。